Python 中的两个变量具有相同的 id,但不是列表或元组

Two variables in Python have same id, but not lists or tuples

Python中的两个变量具有相同的id:

a = 10
b = 10
a is b
>>> True

如果我拿两个 lists:

a = [1, 2, 3]
b = [1, 2, 3]
a is b
>>> False

根据 this link Senderle 的回答,不可变对象引用具有相同的 ID,而可变对象(如列表)具有不同的 ID。

所以现在根据他的回答,元组应该有相同的 id - 意思是:

a = (1, 2, 3)
b = (1, 2, 3)
a is b
>>> False

理想情况下,由于元组不可变,它应该 return True,但它是 returning False!

解释是什么?

不可变对象不具有相同的 id,事实上,对于您单独定义的任何类型的对象而言,情况并非如此。一般来说,每次在 Python 中定义一个对象时,都会创建一个具有新标识的新对象。但是,为了优化(大部分),小整数(-5 到 256 之间)和内部字符串有一些例外,具有特殊长度——通常小于 20 个字符——* 它们是单例并且具有相同的 id (实际上是一个具有多个指针的对象)。您可以像下面这样检查:

>>> 30 is (20 + 10)
True
>>> 300 is (200 + 100)
False
>>> 'aa' * 2 is 'a' * 4
True
>>> 'aa' * 20 is 'a' * 40
False

对于自定义对象:

>>> class A:
...    pass
... 
>>> A() is A() # Every time you create an instance you'll have a new instance with new identity
False

另请注意,is 运算符将检查对象的标识,而不是值。如果你想检查你应该使用的值 ==:

>>> 300 == 3*100
True

并且由于对于元组或任何可变类型没有这样的优化或实习规则,如果您定义两个任意大小的相同元组,它们将获得自己的身份,因此不同的对象:

>>> a = (1,)
>>> b = (1,)
>>>
>>> a is b
False

还值得一提的是 "singleton integers" 和 "interned strings" 的规则即使在迭代器中定义也是如此。

>>> a = (100, 700, 400)
>>>
>>> b = (100, 700, 400)
>>>
>>> a[0] is b[0]
True
>>> a[1] is b[1]
False

* 关于此的一篇很好且详细的文章:http://guilload.com/python-string-interning/

不可变 != 同一对象。*

An immutable object is simply an object whose state cannot be altered; 仅此而已。 当一个新的对象被创建时,一个新的地址将被分配给它因此,检查地址是否等于is 将 return False

1 is 1"a" is "a" returns True 的事实是由于 Python 执行的 integer caching and string interning 所以不要让它把你弄糊涂了;它与所讨论的对象 mutable/immutable.

无关

*空的不可变对象 和它们的 isness 确实 return 正确,不过这是一个特殊的实现特定情况。

看看这段代码:

>>> a = (1, 2, 3)
>>> b = (1, 2, 3)
>>> c = a
>>> id(a)
178153080L
>>> id(b)
178098040L
>>> id(c)
178153080L

为了弄清楚为什么 a is c 被评估为 Truea is b 产生 False 我强烈建议您 运行 逐步-在 Online Python Tutor 中执行上面的代码片段。内存中对象的图形表示将使您更深入地了解这个问题(我附上屏幕截图)。

检查下面的代码.. tupils ab 在我们重新分配它们的旧值时保留它们的旧引用(ID)。 (但是,这不会是列表的情况,因为它们是可变的)

最初 ab 具有相同的值 ( (1,2) ),但它们具有不同的 ID。更改它们的值后,当我们将值 (1,2) 重新分配给 ab 时,它们现在引用它们自己的相同 ID( 88264264 和 88283400)。

>>> 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)
>>> 

**勾选 link 也是在读完这篇文章之后。这里还讨论了另一种情况。