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

Ram*_*ury 44 python identity tuples python-3.x python-internals

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

a = 10
b = 10
a is b
>>> True
Run Code Online (Sandbox Code Playgroud)

如果我拿两个lists:

a = [1, 2, 3]
b = [1, 2, 3]
a is b
>>> False
Run Code Online (Sandbox Code Playgroud)

根据这个链接, Senderle回答说,不可变对象引用具有相同的id,而像列表这样的可变对象具有不同的id.

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

a = (1, 2, 3)
b = (1, 2, 3)
a is b
>>> False
Run Code Online (Sandbox Code Playgroud)

理想情况下,由于元组不可变,它应该返回True,但它正在返回False!

解释是什么?

Kas*_*mvd 62

不可变对象不具有相同的功能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
Run Code Online (Sandbox Code Playgroud)

对于自定义对象:

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

另请注意,is操作员将检查对象的标识,而不是值.如果要检查应使用的值==:

>>> 300 == 3*100
True
Run Code Online (Sandbox Code Playgroud)

并且因为对于元组(其他类型)没有这样的规则,如果你定义任何大小的两个相同的元组,它们将得到它们自己的id:

>>> a = (1,)
>>> b = (1,)
>>>
>>> a is b
False
Run Code Online (Sandbox Code Playgroud)

请注意,即使在可变和不可变对象中定义它们,单例整数和实习字符串的事实也是如此:

>>> a = (100, 700, 400)
>>>
>>> b = (100, 700, 400)
>>>
>>> a[0] is b[0]
True
>>> a[1] is b[1]
False
Run Code Online (Sandbox Code Playgroud)

  • 所有小的8位数字在内存中引用相同的对象的事实是CPython实现细节,不应该因任何原因而依赖它 (9认同)
  • @Ram为什么你认为它应该返回True,它们是2个独立的对象(整数)但具有相同的值(不是id).请注意,它们不低于256. (4认同)
  • @Ram我相信您从错误的角度看待这种情况。您应该问自己,为什么它为a [0]和b [0]返回True,而不是为什么为a [1]和b [1]返回false。如果需要有关此内容的更多信息,请参见[我的相关答案](http://stackoverflow.com/a/15172182/510937)。 (2认同)

Jim*_*ard 20

不可变的!=同一个对象.*

不可变对象只是一个状态不能改变的对象; 这就是全部.创建新对象时,将为其分配新地址.因此,检查地址是否相等is将返回False.

1 is 1或者"a" is "a"返回的事实True是由于Python执行的整数缓存和字符串实习,所以不要让它混淆你; 它与有问题的对象无关是可变的/不可变的.


*空的不可变对象确实引用同一个对象,并且它们is确实返回true,但这是一个特殊的实现特定情况.


Ton*_*has 16

看看这段代码:

>>> a = (1, 2, 3)
>>> b = (1, 2, 3)
>>> c = a
>>> id(a)
178153080L
>>> id(b)
178098040L
>>> id(c)
178153080L
Run Code Online (Sandbox Code Playgroud)

为了找出原因,a is c如评估True,而a is b收益率False我强烈建议你跑一步一步的在上面的代码片段网上Python的导师.内存中对象的图形表示将为您提供对此问题的更深入了解(我附加了一个屏幕截图).

在此输入图像描述


归档时间:

查看次数:

6231 次

最近记录:

6 年,12 月 前