Python 如何展平记忆视图?

Python 如何展平记忆视图?,python,memoryview,Python,Memoryview,我有一个memoryview,步幅很小,如下所示: >>> mv.strides (96, 32, 8) 我想将此memoryview写入套接字,但我的网络库似乎希望memoryview具有mv.strips==(1,)。Python中有没有办法将这个内存视图展平 >>> flatten(mv).strides (1,) 理想情况下,这既不会影响底层字节,也不需要副本。我可以用NumPy来做这件事,但如果可能的话,我更愿意把事情概括起来 编辑:下面是一些生

我有一个
memoryview
,步幅很小,如下所示:

>>> mv.strides
(96, 32, 8)
我想将此
memoryview
写入套接字,但我的网络库似乎希望memoryview具有
mv.strips==(1,)
。Python中有没有办法将这个
内存视图展平

>>> flatten(mv).strides
(1,)
理想情况下,这既不会影响底层字节,也不需要副本。我可以用NumPy来做这件事,但如果可能的话,我更愿意把事情概括起来

编辑:下面是一些生成这样一个memoryview的代码 [1]中的
:将numpy作为np导入
在[2]中:x=np.one((2,3,4))
在[3]:x.data中
出[3]:
在[4]中:x.data.strips
Out[4]:(96,32,8)

为了澄清,您可能知道这一点,但我认为最好确保:

  • 跨步元组的长度表示维度的数量,因此
    (1,)
    (8,)
    都是一维的,
    (10,2)
    (20,1)
    都是二维的
  • 对于C-连续数组,步长元组中的最后一个元素表示memoryview中项目的itemsize。这并不总是正确的:有时填充的值会比实际的itemsize大——但在大多数情况下,它表示itemsize
因此,您不仅希望将memoryview展平,还应该将其展平,并将itemsize设置为1

在Python 3.3中,添加了使数组平坦化变得微不足道的方法:

cast(格式[,形状])
将记忆视图转换为新格式或形状。shape默认为[byte\u length//new\u itemsize],这意味着结果视图将是一维的。返回值是一个新的memoryview,但不会复制缓冲区本身。支持的强制转换为1D->C-连续和C-连续->1D

目标格式限制为结构语法中的单个元素本机格式。其中一种格式必须是字节格式(“B”、“B”或“c”)。结果的字节长度必须与原始长度相同

因此,只有当您强制转换为char(
c
)、无符号char(
B
)或有符号char(
B
)并且它是c-连续的时,它才起作用

>>> import numpy as np

>>> memview = memoryview(np.ones((2, 3, 4)))
>>> memview.cast('b').strides   # or 'B' or 'c'
(1, )
但是,这是平坦的,并解释为1字节值。如果您只想将其展平,则需要再次将其转换为原始类型:

>>> memview.cast('b').cast(memview.format)
这将是一维的,但不会有
(1,)
的跨步,因为浮点是8字节(至少如果是
float64
):


内存视图的来源是什么?这不是一个基本的Python类或概念。我只知道cython的这个术语。@hpaulj这是一个python概念:。但最好能确切地知道
memoryview
我们在谈论什么,memoryview确实是Python的一部分。数字社区通常使用它们。我的用户通常会根据numpy计算结果提供它们,但我更喜欢不以numpy为中心的解决方案。如果您不想要以numpy为中心的答案,请添加只使用Python内置内容创建答案的代码。一系列
cast
调用使用非字节格式:
x.data.cast('B').cast('B',shape=[192]).cast('d')
。但是'd'的跨步是
(8,)
。所以
(1,)
的跨步需要兼容的格式。@hpaulj是的,但是使用
.cast('B').cast(memview.format)
更容易。这样就不需要指定形状了。
>>> memview.cast('b').cast(memview.format)
>>> memview.cast('b').cast(memview.format).strides
(8, )