6

我正试图围绕 PEP3118 的 numpy 实现。缓冲区访问在 numpy 中究竟是如何工作的?

>>> p = numpy.getbuffer(numpy.arange(10))
>>> p
<read-write buffer for 0x1003e5b10, size -1, offset 0 at 0x1016ab4b0>
>>> numpy.frombuffer(p)
array([  0.00000000e+000,   4.94065646e-324,   9.88131292e-324,
     1.48219694e-323,   1.97626258e-323,   2.47032823e-323,
     2.96439388e-323,   3.45845952e-323,   3.95252517e-323,
     4.44659081e-323])

所以我得到了意想不到的回报。我希望看到一个包含 0-9 的 10 个元素的数组。我可以进入数组并读/写。

>>> j = numpy.frombuffer(p)
>>> j
array([  0.00000000e+000,   4.94065646e-324,   9.88131292e-324,
     1.48219694e-323,   1.97626258e-323,   2.47032823e-323,
     2.96439388e-323,   3.45845952e-323,   3.95252517e-323,
     4.44659081e-323])
>>> j += 1
>>> j
array([ 1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.])

所以看起来缓冲区正在初始化为全零,然后我可以写入。我期望的功能是能够使用 getbuffer 将数组(使用 arange 或 asarray)直接构建到缓冲区。那不可能吗?

4

2 回答 2

16

你有一个简单的dtype问题。您创建的缓冲区

np.getbuffer(np.arange(10))

dtype=int, 因为默认np.arange使用dtype=int

然后,当您尝试使用

np.frombuffer(p)

您实际上使用的dtype=floatnp.frombuffer. 相反,使用

np.frombuffer(p, dtype=int)

等等,你得到了

array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
于 2012-09-17T15:38:19.737 回答
9

让我对皮埃尔的出色现有答案添加一些评论。

getbuffer仅当您必须切片时才需要:您可以通过属性ndarray检索与整个数组关联的 python 缓冲区对象data

>>> import numpy as np
>>> a = np.arange(10)
>>> a.data == np.getbuffer(a)
True

相反,您不需要将实际的缓冲区对象传递给frombuffer函数,每个暴露buffer接口的对象都是好的。

>>> np.frombuffer(a, a.dtype)
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> np.frombuffer(a)
array([  0.00000000e+000,   4.94065646e-324,   9.88131292e-324,
         1.48219694e-323,   1.97626258e-323,   2.47032823e-323,
         2.96439388e-323,   3.45845952e-323,   3.95252517e-323,
         4.44659081e-323])
>>> import array
>>> c = array.array('i', range(10))
>>> np.frombuffer(c, np.int32)
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], dtype=int32)
>>> np.frombuffer(c)
array([  2.12199579e-314,   6.36598737e-314,   1.06099790e-313,
         1.48539705e-313,   1.90979621e-313])

解码缓冲区对象时,您必须知道正确dtype的,如上面的示例所示。更准确地说,缓冲区对象没有dtype: 它们只是二进制数据流。相反,ndarray对象有一个dtype指示如何解释底层二进制数据的 。

回答您的问题:每个 numpy 都ndarray公开缓冲区接口。您可以通过data描述符或getbuffer函数访问缓冲区或缓冲区的一部分。您可以通过该函数ndarray从暴露缓冲区接口的对象创建's。frombuffer由于缓冲区(相对于ndarrays)没有dtype信息,因此您应该始终明确指定缓冲区必须如何通过dtype参数来解释frombuffer

于 2012-09-17T23:11:39.173 回答