在纯 Python 中转置 `memoryview`
Transposing `memoryview` in pure Python
是否有一种纯粹的 Python 转置 memoryview
的方法?
Python memoryview
s 不仅仅可以表示一维字节块。它们可以表示多维布局、非连续内存、复杂元素类型等。例如,在下面的代码中:
In [1]: import numpy
In [2]: x = numpy.array([[1, 2], [3, 4]])
In [3]: y = x.T
In [4]: a = memoryview(x)
In [5]: b = memoryview(y)
a
和 b
是 2×2 多维内存视图:
In [6]: a.shape
Out[6]: (2, 2)
In [7]: b.shape
Out[7]: (2, 2)
和b
表示a
的转置,因此a[i, j]
和b[j, i]
别名相同的内存(即原[=23的单元格i,j =]数组):
In [8]: a[0, 1] = 5
In [9]: b[1, 0]
Out[9]: 5
In [10]: x
Out[10]:
array([[1, 5],
[3, 4]])
NumPy 数组支持简单的转置,但 NumPy 数组并不是多维内存视图的唯一来源。例如,您可以投射一维内存视图:
In [11]: bytearr = bytearray([1, 2, 3, 4])
In [12]: mem = memoryview(bytearr).cast('b', (2, 2))
In [13]: mem.shape
Out[13]: (2, 2)
In [14]: mem[1, 0] = 5
In [15]: bytearr
Out[15]: bytearray(b'\x01\x02\x05\x04')
memoryview 格式足够灵活,可以表示 mem
的转置,就像我们之前示例中 b
对 a
的转置一样,但似乎没有内存视图中的简单转置方法 API。是否有一种纯粹的Python转置任意多维记忆视图的方法?
这可能对您有帮助:
>>> import numpy as np
>>> import array
>>> a = array.array('l', [-11111111, 22222222, -33333333, 44444444])
>>> m = memoryview(a)
>>> m_copy = np.array(m)[np.newaxis]
>>> m_copy
array([[-11111111, 22222222, -33333333, 44444444]])
>>> m_copy.T
array([[-11111111],
[ 22222222],
[-33333333],
[ 44444444]])
不使用 numpy:
import array
a = array.array('l', [-11111111, 22222222, -33333333, 44444444])
print(a)
#output:
array('l', [-11111111, 22222222, -33333333, 44444444])
m = memoryview(a)
a = [[x for x in m]]
result = list(map(list, zip(*a)))
print(result)
#output:
[[-11111111], [22222222], [-33333333], [44444444]]
不依赖就没有好办法。使用 NumPy,它非常简单,只要内存视图没有 suboffsets:
transposed = memoryview(numpy.asarray(orig_memoryview).T)
orig_memoryview
可以由任何东西支持 - 后面不一定要有 NumPy 数组。
与其他答案不同,生成的内存视图由与原始内存视图相同的内存支持。例如,使用以下多维内存视图:
In [1]: import numpy
In [2]: arr = numpy.array([[1, 2], [3, 4]])
In [3]: mem = memoryview(arr)
我们可以转置它:
In [4]: transposed = memoryview(numpy.asarray(mem).T)
并写入转置内存视图影响原始数组:
In [5]: transposed[0, 1] = 5
In [6]: arr
Out[6]:
array([[1, 2],
[5, 4]])
这里写入转置的第0、1单元格对应原数组的第1、0单元格
这不依赖于由 NumPy 数组支持的原始内存视图。它适用于由其他东西支持的内存视图,比如 bytearray
s:
In [7]: x = bytearray([1, 2, 3, 4])
In [8]: y = memoryview(x).cast('b', (2, 2))
In [9]: transposed = memoryview(numpy.asarray(y).T)
In [10]: transposed[0, 1] = 5
In [11]: y[1, 0]
Out[11]: 5
In [12]: x
Out[12]: bytearray(b'\x01\x02\x05\x04')
没有 NumPy 或类似的依赖项,我看不出什么好方法。最接近好的方法是使用 ctypes,但您需要为此硬编码 Py_buffer
结构布局,并且 Py_buffer
结构的确切布局没有记录。 (field order and types don't quite match the order in which the fields are documented, or the types they're documented with.) Also, for a PIL-style array with suboffsets,如果不复制数据就无法转置内存视图。
好的一面是,在处理多维内存视图的大多数情况下,您已经拥有转置它们所需的依赖项。
是否有一种纯粹的 Python 转置 memoryview
的方法?
Python memoryview
s 不仅仅可以表示一维字节块。它们可以表示多维布局、非连续内存、复杂元素类型等。例如,在下面的代码中:
In [1]: import numpy
In [2]: x = numpy.array([[1, 2], [3, 4]])
In [3]: y = x.T
In [4]: a = memoryview(x)
In [5]: b = memoryview(y)
a
和 b
是 2×2 多维内存视图:
In [6]: a.shape
Out[6]: (2, 2)
In [7]: b.shape
Out[7]: (2, 2)
和b
表示a
的转置,因此a[i, j]
和b[j, i]
别名相同的内存(即原[=23的单元格i,j =]数组):
In [8]: a[0, 1] = 5
In [9]: b[1, 0]
Out[9]: 5
In [10]: x
Out[10]:
array([[1, 5],
[3, 4]])
NumPy 数组支持简单的转置,但 NumPy 数组并不是多维内存视图的唯一来源。例如,您可以投射一维内存视图:
In [11]: bytearr = bytearray([1, 2, 3, 4])
In [12]: mem = memoryview(bytearr).cast('b', (2, 2))
In [13]: mem.shape
Out[13]: (2, 2)
In [14]: mem[1, 0] = 5
In [15]: bytearr
Out[15]: bytearray(b'\x01\x02\x05\x04')
memoryview 格式足够灵活,可以表示 mem
的转置,就像我们之前示例中 b
对 a
的转置一样,但似乎没有内存视图中的简单转置方法 API。是否有一种纯粹的Python转置任意多维记忆视图的方法?
这可能对您有帮助:
>>> import numpy as np
>>> import array
>>> a = array.array('l', [-11111111, 22222222, -33333333, 44444444])
>>> m = memoryview(a)
>>> m_copy = np.array(m)[np.newaxis]
>>> m_copy
array([[-11111111, 22222222, -33333333, 44444444]])
>>> m_copy.T
array([[-11111111],
[ 22222222],
[-33333333],
[ 44444444]])
不使用 numpy:
import array
a = array.array('l', [-11111111, 22222222, -33333333, 44444444])
print(a)
#output:
array('l', [-11111111, 22222222, -33333333, 44444444])
m = memoryview(a)
a = [[x for x in m]]
result = list(map(list, zip(*a)))
print(result)
#output:
[[-11111111], [22222222], [-33333333], [44444444]]
不依赖就没有好办法。使用 NumPy,它非常简单,只要内存视图没有 suboffsets:
transposed = memoryview(numpy.asarray(orig_memoryview).T)
orig_memoryview
可以由任何东西支持 - 后面不一定要有 NumPy 数组。
与其他答案不同,生成的内存视图由与原始内存视图相同的内存支持。例如,使用以下多维内存视图:
In [1]: import numpy
In [2]: arr = numpy.array([[1, 2], [3, 4]])
In [3]: mem = memoryview(arr)
我们可以转置它:
In [4]: transposed = memoryview(numpy.asarray(mem).T)
并写入转置内存视图影响原始数组:
In [5]: transposed[0, 1] = 5
In [6]: arr
Out[6]:
array([[1, 2],
[5, 4]])
这里写入转置的第0、1单元格对应原数组的第1、0单元格
这不依赖于由 NumPy 数组支持的原始内存视图。它适用于由其他东西支持的内存视图,比如 bytearray
s:
In [7]: x = bytearray([1, 2, 3, 4])
In [8]: y = memoryview(x).cast('b', (2, 2))
In [9]: transposed = memoryview(numpy.asarray(y).T)
In [10]: transposed[0, 1] = 5
In [11]: y[1, 0]
Out[11]: 5
In [12]: x
Out[12]: bytearray(b'\x01\x02\x05\x04')
没有 NumPy 或类似的依赖项,我看不出什么好方法。最接近好的方法是使用 ctypes,但您需要为此硬编码 Py_buffer
结构布局,并且 Py_buffer
结构的确切布局没有记录。 (field order and types don't quite match the order in which the fields are documented, or the types they're documented with.) Also, for a PIL-style array with suboffsets,如果不复制数据就无法转置内存视图。
好的一面是,在处理多维内存视图的大多数情况下,您已经拥有转置它们所需的依赖项。