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