Numpy | hex(id()) vs. .data



我有两个问题已经处理了两天:

如果我想用numpy方法.array为numpy对象确定对象和元素的内存地址,一旦使用普通python函数hex(id(,我就会得到不同的地址。使用hex(id(((会变得非常奇怪。有时元素得到相同的地址,有时得到不同的地址。

import numpy as np
y = np.array([0,1,2,3])
print(y.data)
print(y[0].data)
print(y[1].data)
print(y[2].data)
print(y[3].data)
print(hex(id(y[0])))
print(hex(id(y[1])))
print(hex(id(y[2])))
print(hex(id(y[3])))

结果是:

<memory at 0x7f9aaa22d870>
<memory at 0x7f9aaa1bd940>
<memory at 0x7f9aaa1bd940>
<memory at 0x7f9aaa1bd940>
<memory at 0x7f9aaa1bd940>
0x7f9aaa31e030
with hex((id))
0x7f9aaa1c0750
0x7f9aaa1c0730
0x7f9aaa1c0130
0x7f9aaa1c0750

这些结果中的大多数并不代表您的想法,因为NumPy内存布局的工作方式与您的想法不同。

NumPy数组对象不是其数据缓冲区。数据缓冲区是独立的。有了数组所需的所有元数据,数组就不可能真正成为其数据缓冲区,而NumPy大量使用数组视图,数组也不可能直接包含其缓冲区。许多阵列可以共享同一个数据缓冲区,或者具有重叠的数据缓冲区。

NumPy数组对象包含一些元数据和一些指针,其中一个指针指向其缓冲区。如果您执行了print(hex(id(y))),那么您将获得数组对象本身的地址。使用print(y.data),可以打印一个表示数组数据缓冲区的memoryview对象;在0x"给出缓冲区的地址。


当您执行y[0]时,它实际上不是一个数组元素。它是一个新的数组标量对象,表示一个不可变的标量,其值取自y的第一个索引。它不是直接引用用于y的第一个元素的内存,因为当有人执行时

x = y[0]
y[0] = 1

他们不希望CCD_ 6的分配影响CCD_。

数组标量有自己的地址和数据缓冲区,与数组标量本身分离。数组标量的生存期非常短,因此如果y[0]的生存期在检索y[1]之前结束,则y[0]y[1]可能最终使用相同的内存。他们没有使用相同的内存,但他们可以。

当您执行print(hex(id(y[0])))时,您正在打印数组标量的地址。当您执行print(y[0].data)时,您正在打印一个表示数组标量的数据缓冲区的内存视图。


尽管如此,你对这些内存地址几乎没有任何用处,尤其是如果你没有写C扩展名的话。如果正在编写C扩展,那么您可能仍然不应该直接使用这些地址中的任何一个。Cython比直接编写C代码要方便得多。如果你真的想写C来与NumPy交互,你会想更深入地了解NumPy数组是如何在引擎盖下工作的,你应该去阅读NumPy C API文档。

最新更新