【发布时间】:2016-03-06 22:27:42
【问题描述】:
考虑两种天真地创建相同bytearray 的方法(使用 Python 2.7.11,但在 3.4.3 中也确认了相同的行为):
In [80]: from array import array
In [81]: import numpy as np
In [82]: a1 = array('L', [1, 3, 2, 5, 4])
In [83]: a2 = np.asarray([1,3,2,5,4], dtype=int)
In [84]: b1 = bytearray(a1)
In [85]: b2 = bytearray(a2)
由于array.array 和numpy.ndarray 都支持缓冲协议,我希望两者都在转换到bytearray 时导出相同的基础数据。
但是上面的数据:
In [86]: b1
Out[86]: bytearray(b'\x01\x03\x02\x05\x04')
In [87]: b2
Out[87]: bytearray(b'\x01\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00')
起初我认为,由于数据类型、连续性或其他一些开销数据,对 NumPy 数组的 bytearray 的天真调用可能会无意中获得一些额外的字节。
但即使直接查看 NumPy 缓冲区数据句柄,它仍然显示大小为 40 并给出相同的数据:
In [90]: a2.data
Out[90]: <read-write buffer for 0x7fb85d60fee0, size 40, offset 0 at 0x7fb85d668fb0>
In [91]: bytearray(a2.data)
Out[91]: bytearray(b'\x01\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00')
a2.view() 发生同样的失败:
In [93]: bytearray(a2.view())
Out[93]: bytearray(b'\x01\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00')
我注意到如果我给了dtype=np.int32,那么bytearray(a2) 的长度是20 而不是40,这表明额外的字节与类型信息有关——只是不清楚为什么或如何:
In [20]: a2 = np.asarray([1,3,2,5,4], dtype=int)
In [21]: len(bytearray(a2.data))
Out[21]: 40
In [22]: a2 = np.asarray([1,3,2,5,4], dtype=np.int32)
In [23]: len(bytearray(a2.data))
Out[23]: 20
AFAICT,np.int32 应该对应于 array 'L' 类型代码,但任何关于为什么不的解释都会有很大帮助。
如何才能可靠地仅提取“应该”通过缓冲区协议导出的数据部分......就像在这种情况下,与普通 array 数据一样。
【问题讨论】:
-
“应该”被导出是什么意思?缓冲区协议只是指定如何获取数据,并没有说明数据应该是什么。
-
这是因为 numpy 默认为 64 位(16 个半字节)吗?尝试改变字节顺序(大端,小端),看看会发生什么。看到这个docs.scipy.org/doc/numpy/reference/arrays.dtypes.html
标签: python numpy buffer bytearray protocol-buffers