How to flatten a memoryview?

MRo*_*lin 5 python memoryview

I have a memoryview with non-trivial strides like the following:

>>> mv.strides
(96, 32, 8)
Run Code Online (Sandbox Code Playgroud)

I want to write this memoryview to a socket but my networking library seems to expect memoryviews with mv.strides == (1,). Is there a way in Python to flatten this memoryview?

>>> flatten(mv).strides
(1,)
Run Code Online (Sandbox Code Playgroud)

Ideally this would neither affect the underlying bytes nor require a copy. I could do this with NumPy, but I'd rather keep things general if possible.

Edit: Here is some code that produces such a memoryview

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)
Run Code Online (Sandbox Code Playgroud)

MSe*_*ert 5

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

\n
    \n
  • strides 元组的长度表示维数,因此(1, )(8, )都是一维,并且(10, 2)(20, 1)都是二维。
  • \n
  • 对于 C 连续数组,步幅元组中的最后一个元素表示内存视图中项目的项目大小。这并不总是正确的:有时这些值会被填充,然后它会大于实际的项目大小 - 但在大多数情况下它代表项目大小。
  • \n
\n

因此,您不仅希望您的内存视图扁平化,而且还应该扁平化并且其项目大小为 1

\n

在 Python 3.3 中memoryview.cast添加了该方法,使数组变得简单:

\n
\n

cast(format[, shape])

\n

将内存视图转换为新的格式或形状。shape 默认为 [byte_length//new_itemsize],这意味着结果视图将是一维的。返回值是一个新的内存视图,但缓冲区本身没有被复制。支持的转换为 1D -> C-连续和 C-连续 -> 1D。

\n

目标格式仅限于结构语法中的单个元素本机格式。其中一种格式必须是字节格式(\xe2\x80\x98B\xe2\x80\x99、\xe2\x80\x98b\xe2\x80\x99 或 \xe2\x80\x98c\xe2\x80\x99)。结果的字节长度必须与原始长度相同。

\n
\n

因此,只有当您转换为 char ( c)、unsigned char ( B) 或signed chars ( b) 并且它是 C 连续的时,它才有效。

\n
>>> import numpy as np\n\n>>> memview = memoryview(np.ones((2, 3, 4)))\n>>> memview.cast(\'b\').strides   # or \'B\' or \'c\'\n(1, )\n
Run Code Online (Sandbox Code Playgroud)\n

然而,这被展平并解释为 1 字节值。如果您只想将其展平,则需要再次将其转换为原始类型:

\n
>>> memview.cast(\'b\').cast(memview.format)\n
Run Code Online (Sandbox Code Playgroud)\n

这将是一维的,但不会有 的步幅,(1, )因为浮点数是 8 个字节(至少如果是 的话float64):

\n
>>> memview.cast(\'b\').cast(memview.format).strides\n(8, )\n
Run Code Online (Sandbox Code Playgroud)\n