Python 中的两个整数具有相同的 id,但列表或元组则不然

问题描述 投票:0回答:5

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

解释是什么?

python python-3.x tuples identity python-internals
5个回答
87
投票

不可变对象没有相同的

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

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

25
投票

不可变

!=
同一个对象。*

不可变对象只是一个状态不能改变的对象;仅此而已。 创建新对象时,将为其分配新地址因此,检查地址是否与

is
相等将返回
False

1 is 1
"a" is "a"
返回
True
的事实是由于Python执行的整数缓存和字符串驻留,所以不要让它让你感到困惑;它与所讨论的对象的可变/不可变无关。


*空的不可变对象确实引用同一个对象并且它们的

is
ness确实返回true,但这是一个特殊的实现特定情况。


20
投票

看一下这段代码:

>>> 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 中逐步运行上面的代码片段。内存中对象的图形表示将使您更深入地了解这个问题(我附上了屏幕截图)。


1
投票

根据文档,不可变对象可能具有相同的 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

0
投票

检查下面的代码.. 当我们重新分配它们的旧值时,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)
>>> 

**检查链接 为什么元组在分配相同的值时不会获得相同的 ID? 也是在读完这篇文章之后。这里还讨论了另一个案例。

© www.soinside.com 2019 - 2024. All rights reserved.