Python 中的两个变量具有相同的 id,但不是列表或元组
Two variables in Python have same id, but not lists or tuples
Python中的两个变量具有相同的id
:
a = 10
b = 10
a is b
>>> True
如果我拿两个 list
s:
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.
无关
*空的不可变对象 和它们的 is
ness 确实 return 正确,不过这是一个特殊的实现特定情况。
看看这段代码:
>>> 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 中执行上面的代码片段。内存中对象的图形表示将使您更深入地了解这个问题(我附上屏幕截图)。
检查下面的代码..
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)
>>>
**勾选 link
也是在读完这篇文章之后。这里还讨论了另一种情况。
Python中的两个变量具有相同的id
:
a = 10
b = 10
a is b
>>> True
如果我拿两个 list
s:
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.
*空的不可变对象 is
ness 确实 return 正确,不过这是一个特殊的实现特定情况。
看看这段代码:
>>> 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 中执行上面的代码片段。内存中对象的图形表示将使您更深入地了解这个问题(我附上屏幕截图)。
检查下面的代码.. 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)
>>>
**勾选 link