即使两个对象具有相同的ID,“ is”操作也会返回false

时间:2019-04-12 19:19:25

标签: python numpy

两个python对象具有相同的id,但是“ is”操作返回false,如下所示:

a = np.arange(12).reshape(2, -1)
c = a.reshape(12, 1)
print("id(c.data)", id(c.data))
print("id(a.data)", id(a.data))

print(c.data is a.data)
print(id(c.data) == id(a.data))

这是实际输出:

id(c.data) 241233112
id(a.data) 241233112
False
True

我的问题是...为什么“ c.data是a.data”即使它们指向相同的ID也指向相同的对象却返回false?我以为如果它们具有相同的ID,则它们指向相同的对象,或者我错了吗?谢谢!

2 个答案:

答案 0 :(得分:16)

a.datac.data都产生一个 transient 对象,但没有对其进行引用。这样,两者都会立即被垃圾收集。两者可以使用相同的ID。

在您的第一个if语句中,对象必须共存,而is则检查它们是否相同。

在第二个if语句中,id一旦返回其ID,就会释放每个对象。

如果保存对两个对象的引用,并使它们保持活动状态,则可以看到它们不是同一对象。

r0 = a.data
r1 = c.data
assert r0 is not r1

答案 1 :(得分:6)

In [62]: a = np.arange(12).reshape(2,-1) 
    ...: c = a.reshape(12,1)                                                    

.data返回一个memoryview对象。 id仅给出该对象的ID;它不是对象的值,也不是a数据缓冲区所在位置的任何指示。

In [63]: a.data                                                                 
Out[63]: <memory at 0x7f672d1101f8>
In [64]: c.data                                                                 
Out[64]: <memory at 0x7f672d1103a8>
In [65]: type(a.data)                                                           
Out[65]: memoryview

https://docs.python.org/3/library/stdtypes.html#memoryview

如果您想验证ac共享一个数据缓冲区,我发现__array_interface__是一个更好的工具。

In [66]: a.__array_interface__['data']                                          
Out[66]: (50988640, False)
In [67]: c.__array_interface__['data']                                          
Out[67]: (50988640, False)

它甚至显示切片产生的偏移量-这里是24字节,3 * 8

In [68]: c[3:].__array_interface__['data']                                      
Out[68]: (50988664, False)

我还没有看到a.data的大量使用。当使用buffer创建新数组时,它可用作ndarray对象:

In [70]: d = np.ndarray((2,6), dtype=a.dtype, buffer=a.data)                    
In [71]: d                                                                      
Out[71]: 
array([[ 0,  1,  2,  3,  4,  5],
       [ 6,  7,  8,  9, 10, 11]])
In [72]: d.__array_interface__['data']                                          
Out[72]: (50988640, False)

但是通常我们会使用切片或np.array(copy = False)创建具有共享内存的新阵列。