Jzl*_*325 6 python buffer numpy
我试图围绕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])
Run Code Online (Sandbox Code Playgroud)
所以我得到了意想不到的回报.我希望看到一个包含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.])
Run Code Online (Sandbox Code Playgroud)
所以看起来缓冲区正在初始化为全零,然后我可以写入.我期望的功能是能够使用getbuffer将数组(使用arange或asarray)直接构建到缓冲区.这不可能吗?
Pie*_* GM 15
你有一个简单的dtype
问题.您创建的缓冲区
np.getbuffer(np.arange(10))
Run Code Online (Sandbox Code Playgroud)
有一个dtype=int
,因为默认np.arange
使用dtype=int
.
然后,当您尝试使用时读取缓冲区
np.frombuffer(p)
Run Code Online (Sandbox Code Playgroud)
你实际上使用的是dtype=float
默认值np.frombuffer
.相反,使用
np.frombuffer(p, dtype=int)
Run Code Online (Sandbox Code Playgroud)
etvoilà,你明白了
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
Run Code Online (Sandbox Code Playgroud)
让我对皮埃尔现有的优秀答案补充一些评论.
getbuffer
只有在必须切片时才需要ndarray
:您可以通过data
属性检索与整个数组关联的python缓冲区对象
>>> import numpy as np
>>> a = np.arange(10)
>>> a.data == np.getbuffer(a)
True
Run Code Online (Sandbox Code Playgroud)
相反,您不需要将实际的缓冲区对象传递给该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])
Run Code Online (Sandbox Code Playgroud)
当解码一个缓冲区对象,你必须知道正确的dtype
上面的例子演示.更确切地说,缓冲对象没有dtype
:它们只是二进制数据流.相反,ndarray
对象具有dtype
指示如何解释基础二进制数据的对象.
回答你的问题:每个numpy ndarray
暴露缓冲区接口.您可以通过data
描述符或getbuffer
函数访问缓冲区或其片段.您可以ndarray
通过该frombuffer
函数从对象创建缓冲区接口.由于缓冲区(而不是ndarrays
)没有dtype
信息,因此您应该始终明确指定缓冲区必须通过dtype
参数来解释frombuffer
.