比较两个 numpy 数组的对象 ID

Comparing object ids of two numpy arrays

我使用 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 值。这是预期的行为吗?

简短的回答是,您应该忘记依赖 id 来尝试深入了解 python 的工作原理。它的输出受 CPython 实现细节、窥孔优化和内存重用的影响。 id 通常是转移注意力。对于 numpy 尤其如此。

在您的特定情况下,只有 ab 作为 python 对象存在。当你获取一个元素 a[0] 时,你实例化了一个新的 python 对象,一个 numpy.float64 类型的标量。这些是新的 python 对象,因此被赋予新的 id 除非 解释器意识到您正在尝试使用该对象两次(这可能是发生在你中间的例子中,虽然我确实发现令人惊讶的是两个具有不同值的 numpy.float64 对象被赋予相同的 id。但是如果你分配 a[0]b[0] 到专有名称,所以这可能是由于一些优化)。也可能发生内存地址被解释器重用,给你 ids 以前出现过。

看看 id 对 numpy 有多么无意义,即使是琐碎的视图也是具有新 id 的新 python 对象,尽管从所有意图和目的来看它们都一样好作为原文:

>>> arr = np.arange(3)

>>> id(arr)
140649669302992

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

下面是 id 在交互式 shell 中重用的示例:

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

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

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

对于 numpy 数组肯定没有 int interning 之类的东西,所以以上只是由于解释器重用了 ids。 id returns 一个内存地址的事实再次只是一个 CPython 实现细节。忘记 id.

您可能唯一想与 numpy 一起使用的是 numpy.may_share_memory and numpy.shares_memory

重要的是要注意 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 在生命周期内保持不变。 float 0.0 和其他对象的情况类似。 因此,在您的情况下,a[0]b[0] 零对象 ID 将保持不变,直到或除非它还活着,因为它们都包含 0 作为对象值。 每次你在不同的行打印 a[0]b[0] 你 return 它是不同的对象标识,因为你在不同的行触发它因此不同的生命周期。 你可以试试:

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

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