Fra*_*lin 5 python swig memoryview
为什么 Python 告诉我记录的内存视图是只读的?
>>> x = np.zeros(1, dtype='d,d,i')
>>> x
array([(0., 0., 0)], dtype=[('f0', '<f8'), ('f1', '<f8'), ('f2', '<i4')])
>>> memoryview(x).readonly
False
>>> memoryview(x[0]).readonly
True
Run Code Online (Sandbox Code Playgroud)
显然,x[0]不是只读的,因为
>>> x[0][0] += 1
>>> x[0]
(1., 0., 0)
Run Code Online (Sandbox Code Playgroud)
内存视图对于普通数组没有问题:
>>> y = np.zeros((3, 4))
>>> memoryview(y).readonly
False
>>> memoryview(y[0]).readonly
False
Run Code Online (Sandbox Code Playgroud)
同样,不推荐使用的人__array_info__知道它x[0]是读写的:
>>> x.__array_interface__['data'] # returns tuple (address, read-only)
(105553143159680, False)
>>> x[0].array_interface__['data']
(105553143159680, False)
Run Code Online (Sandbox Code Playgroud)
我的实际问题是 C 代码。幸运的是,我的所有问题也可以用纯 Python 显示。
我正在尝试用 C 代码读取和写入 numpy 记录,我只需要数据的地址。__array_interface__我可以使用它相应的 C-side找到数据的地址__array_struct__。但该页面上有一条注释说这是遗留的,新代码应该使用缓冲区协议。
但缓冲区协议( Python 中模仿的memoryview)认为该记录是只读的。我必须特别要求一个只读缓冲区。是的,我可以从“只读”缓冲区获取数据的地址,然后写入它,但这感觉很脏。
更新以回应@tdelaney 的评论:
作为实验,我编写了一个小型 C 函数,该函数请求只读内存缓冲区,找到起始地址,并在那里递增双精度,尽管这是不应该的。
void foo(PyObject *object) {
Py_buffer view;
PyObject_GetBuffer(object, &view, PyBUF_CONTIG_RO);
if (view.obj) {
double *data = (double *)view.buf;
*data += 1;
}
PyBuffer_Release(&view);
}
Run Code Online (Sandbox Code Playgroud)
然后我可以在 Python 中查看生成的数组。
对于记录数组, 和 都foo(x)正确foo(x[1])地递增了数组元素。
对于二维双精度数组, 和 都foo(y)正确foo(y[1])地递增了数组元素。正如所料,foo(y[1][2])什么也没做。
因此,对于记录,np.void不会复制。至少在本案中是这样。