Python 中的两个整数具有相同的
id
:
a = 10
b = 10
a is b
>>> True
如果我拿两个
list
:
a = [1, 2, 3]
b = [1, 2, 3]
a is b
>>> False
根据此链接 Senderle 回答说,不可变对象引用具有相同的 id,而可变对象(如列表)具有不同的 id。
所以现在根据他的回答,元组应该有相同的 id - 意思是:
a = (1, 2, 3)
b = (1, 2, 3)
a is b
>>> False
理想情况下,由于元组不可变,它应该返回
True
,但它正在返回 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
还值得一提的是,“单例整数”和“内部字符串”的规则是正确的,即使它们是在迭代器中定义的。
>>> a = (100, 700, 400)
>>>
>>> b = (100, 700, 400)
>>>
>>> a[0] is b[0]
True
>>> a[1] is b[1]
False
不可变
!=
同一个对象。*
不可变对象只是一个状态不能改变的对象;仅此而已。 创建新对象时,将为其分配新地址。因此,检查地址是否与
is
相等将返回False
。
1 is 1
或"a" is "a"
返回True
的事实是由于Python执行的整数缓存和字符串驻留,所以不要让它让你感到困惑;它与所讨论的对象的可变/不可变无关。
*空的不可变对象确实引用同一个对象并且它们的
is
ness确实返回true,但这是一个特殊的实现特定情况。
看一下这段代码:
>>> a = (1, 2, 3)
>>> b = (1, 2, 3)
>>> c = a
>>> id(a)
178153080L
>>> id(b)
178098040L
>>> id(c)
178153080L
为了弄清楚为什么
a is c
被评估为 True
而 a is b
产生 False
我强烈建议您在 Online Python Tutor 中逐步运行上面的代码片段。内存中对象的图形表示将使您更深入地了解这个问题(我附上了屏幕截图)。
根据文档,不可变对象可能具有相同的 id,但不能保证它们具有相同的 id。可变的总是有不同的 id。
https://docs.python.org/3/reference/datamodel.html#objects-values-and-types
类型影响对象行为的几乎所有方面。甚至对象标识的重要性在某种意义上也受到影响:对于不可变类型,计算新值的操作实际上可能返回对具有相同类型和值的任何现有对象的引用,而对于可变对象,这是不允许的。
在Python的早期版本中,元组被分配了不同的ID。 (3.7 之前)
从 Python 3.7+ 开始,分配了相同元组的两个变量可能具有相同的 id:
>>>a = (1, 2, 3)
>>>b = (1, 2, 3)
>>>a is b
True
256 以上的整数也有不同的 id:
>>>a = 123
>>>b = 123
>>>a is b
True
>>>
>>>a = 257
>>>b = 257
>>>a is b
False
检查下面的代码.. 当我们重新分配它们的旧值时,tupils a 和 b 会保留它们旧的引用(ID)。 (但是,列表不会出现这种情况,因为它们是可变的)
最初 a 和 b 具有相同的值 ( (1,2) ),但它们具有不同的 ID。更改其值后,当我们将值 (1,2) 重新分配给 a 和 b 时,它们现在引用自己的相同 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)
>>>
**检查链接 为什么元组在分配相同的值时不会获得相同的 ID? 也是在读完这篇文章之后。这里还讨论了另一个案例。