比较两个Numpy数组的对象ID

时间:2019-02-11 06:09:52

标签: python python-3.x numpy numpy-ndarray

我已经使用numpy已有一段时间了,但偶然发现了我不完全了解的一件事:

a = np.ones(20)
b = np.zeros(10)

print(id(a)==id(b))          # prints False
print(id(a), id(b))          # prints (4591424976, 4590843504)

print(id(a[0])==id(b[0]))    # prints True 
print(id(a[0]), id(b[0]))    # prints (4588947064, 4588947064)

print(id(a[0]))              # 4588947184
print(id(b[0]))              # 4588947280

有人可以解释一下最近四个打印语句中观察到的行为吗?另外,我知道id为您提供了实际上在内存中分配的唯一对象ID的事实,但是每次我运行最后两个打印语句时,我都会得到不同的id值。这是预期的行为吗?

2 个答案:

答案 0 :(得分:5)

简短的答案是,您应该忘记依赖id来尝试深入了解python的工作原理。其输出受cpython实现细节,窥孔优化和内存重用的影响。 id通常是红色鲱鱼。对于numpy尤其如此。

在您的特定情况下,只有ab作为python对象存在。当您使用元素a[0]时,您将实例化一个新的python对象,类型为numpy.float64(或者取决于系统,numpy.float32)的标量。这些是新的python对象,因此被赋予了新的id,除非解释器意识到 ,否则您将尝试使用该对象两次(这可能是中间示例中发生的情况,尽管我确实感到惊讶,两个具有不同值的numpy.float64对象被赋予相同的id,但是如果先为专有名称分配a[0]b[0],那么奇怪的魔术就消失了,因此这可能是由于进行了一些优化)。内存地址也有可能被解释器重用,从而给您id个以前出现过的地址。

仅查看numpy的id毫无意义,即使琐碎的视图也是具有新id的新python对象,即使它们在所有目的和用途上都与原始的一样好

>>> arr = np.arange(3)

>>> id(arr)
140649669302992

>>> id(arr[...])
140649669667056

这是id在交互式外壳中重用的示例:

>>> id(np.arange(3))
140649669027120

>>> id(np.arange(3))
140649669028480

>>> id(np.arange(3))
140649669026480

对于numpy数组,肯定没有int interning这样的东西,因此以上内容仅是由于解释器重用了id s。 id返回一个内存地址的事实再次只是一个cpython实现细节。忘记id

您可能只想将numpy与numpy.may_share_memorynumpy.shares_memory一起使用。

答案 1 :(得分:0)

请务必注意,Python中的所有内容都是对象,甚至是数字和类。 您已获取2个numpy数组对象,每个对象都包含相同的值,即0。 当你说:

print('id of 0 =',id(0))

a = 0
print('id of a =',id(a))

b = a
print('id of b =',id(b))

c = 0.0
print('id of c =',id(c))

得到的答案类似(您的情况不同)

id of 0 = 140472391630016
id of a = 140472391630016
id of b = 140472391630016
id of c = 140472372786520

因此,整数0具有唯一的ID。整数0的ID在生存期内保持不变。浮动0.0和其他对象的情况与此类似。 因此,在您的情况下,a[0]b[0]的对象ID为零将一直保持不变,直到或除非它是有效的,否则因为它们都包含0作为对象值。 每次在不同的行中打印a[0]b[0]时,都会返回不同的对象标识,因为您在不同的行触发了它,因此生命周期也不同。 您可以尝试:

print(id(a)==id(b))
print(id(a),id(b))
print(id(a[0])==id(b[0]))
print(id(a[0]),id(b[0]))

输出将是:

False
2566443478752 2566448028528
True
2566447961120 2566447961120

请注意,第二行将返回给您2个不同的numpy数组类型对象的标识,因为它们都是不同的列表。