为什么元组在分配相同的值时不会获得相同的 ID?

Why don't tuples get the same ID when assigned the same values?

当我执行以下步骤时,两个元组(ab)即使在我重新分配旧值((1,2))时也没有保留它们的原始 ID。

>>> a , b = (1,2) , (1,2)
>>> a
(1, 2)
>>> b
(1, 2)
>>> id(a) , id(b)
(80131912, 91541064)
>>> a , b = (3,4) , (3,4)
>>> a
(3, 4)
>>> b
(3, 4)
>>> id(a) , id(b)
(91559048, 91689032)
>>> a , b = (1,2) , (1,2)
>>> a
(1, 2)
>>> b
(1, 2)
>>> id(a) , id(b)
(91556616, 91550408)

但在以下情况中,两者都已取回旧 ID。

>>> a = (1,2)
>>> b = (1,2)
>>> a , b
((1, 2), (1, 2))
>>> id(a)
88264264
>>> id(b)
88283400
>>> a = (3,4)
>>> b = (3,4)
>>> id(a)
88280008
>>> id(b)
88264328
>>> a = (1,2)
>>> b = (1,2)
>>> id(a)
88264264
>>> id(b)
88283400
>>> a , b
((1, 2), (1, 2))
>>> id(a) , id(b)
(88264264, 88283400)

有人可以解释一下吗?

您创建了新的元组对象。它们具有相同的内容并不意味着它们将是内存中完全相同的元组对象。

不变性并不意味着创建相同的 value 将创建相同的 object。你从未改变旧的 (1, 2) 元组,你的新 (1, 2) 元组也不可变。

CPython 确实保留了 re-usable 元组对象的缓存(因此它不必一直创建新对象,Python 会遍历很多小元组在一个典型的程序中),但这是一个你不能依赖的实现细节。对于长度为 2 的元组,正是这个缓存导致相同的 id 再次出现。如果您想了解缓存是如何实现的,请参阅How is tuple implemented in CPython?

此外,在CPython中,id()是对象的内存位置,一旦旧对象被释放,Python就可以释放到re-use内存位置.这是 clearly documented:

This is an integer which is guaranteed to be unique and constant for this object during its lifetime. Two objects with non-overlapping lifetimes may have the same id() value.

新对象总是可以看到相同的 id() 值。有时这意味着您仍然拥有相同的对象(对于小整数或元组或某些类型的字符串对象就是这种情况),有时只是解释器 re-used 在内存中的相同位置。您永远不应该依赖它,这些是用于性能目的的实现细节,可能会发生变化。