如何压平记忆视图?

时间:2017-06-11 16:21:18

标签: python memoryview

我有一个memoryview,其中包含以下非常重要的步幅:

>>> mv.strides
(96, 32, 8)

我想将此memoryview写入套接字,但我的网络库似乎期望使用mv.strides == (1,)进行内存视图。有没有办法在Python中展平这个memoryview

>>> flatten(mv).strides
(1,)

理想情况下,这既不会影响基础字节,也不会需要副本。我可以使用NumPy做到这一点,但是如果可能的话,我宁愿保持一般。

编辑:这是一些产生这种记忆视图的代码

In [1]: import numpy as np
In [2]: x = np.ones((2, 3, 4))
In [3]: x.data
Out[3]: <memory at 0x7f371aa849a8>

In [4]: x.data.strides
Out[4]: (96, 32, 8)

1 个答案:

答案 0 :(得分:1)

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

  • 步幅元组的长度表示维度数,因此(1, )(8, )都是一维的,(10, 2)(20, 1)都是二维的。
  • 对于C-contiguous数组,strides元组中的最后一个元素表示memoryview中项目的itemsize。这并不总是正确的:有时值填充然后它会比实际的项目大 - 但在大多数情况下它代表商品化。

因此,您不仅希望将内存视图展平,而且应该展平并且项目大小为1

在Python 3.3中添加了memoryview.cast方法,使你的数组​​变得平坦:

  

cast(format[, shape])

     

将内存视图转换为新格式或形状。 shape默认为[byte_length // new_itemsize],这意味着结果视图将是一维的。返回值是新的内存视图,但不会复制缓冲区本身。支持的演员阵容是1D - &gt; C-连续和C-连续 - &gt; 1D。

     

目标格式仅限于struct语法中的单个元素本机格式。其中一种格式必须是字节格式('B','b'或'c')。结果的字节长度必须与原始长度相同。

所以它只适用于转换为char(c),unsigned char(B)或signed char(b)并且它是C-contiguous。

>>> 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):

>>> memview.cast('b').cast(memview.format).strides
(8, )