Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python中的两个变量具有相同的id,但不是列表或元组_Python_Python 3.x_Tuples_Identity_Python Internals - Fatal编程技术网

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

Python中的两个变量具有相同的id,但不是列表或元组,python,python-3.x,tuples,identity,python-internals,Python,Python 3.x,Tuples,Identity,Python Internals,Python中的两个变量具有相同的id: a = 10 b = 10 a is b >>> True 如果我选择两个列表s: 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

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

a = 10
b = 10
a is b
>>> True
如果我选择两个
列表
s:

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是1
“a”是“a”
返回
True
这一事实是由Python执行的,因此不要让它迷惑您;它与所讨论的可变/不可变对象无关



*空的不可变对象及其
属性确实返回true,但这是特定于实现的特殊情况

看看这段代码:

>>> a = (1, 2, 3)
>>> b = (1, 2, 3)
>>> c = a
>>> id(a)
178153080L
>>> id(b)
178098040L
>>> id(c)
178153080L
为了弄清楚为什么
a是c
被评估为
True
,而
a是b
产生
False
,我强烈建议您在中逐步运行上面的代码段。内存中对象的图形表示将使您对这个问题有更深入的了解(我附上一个屏幕截图)

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

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

**检查链接
也是看完这个。这里还讨论了另一个案例

你必须区分变量和对象(列表和元组)-当你比较两个这样的对象时,你会比较它们不同的内存地址,尽管它们有相同的列表和元组元素。我想你误解了你链接到的答案。不同的不可变对象具有不同的ID。但是对于小于256的整数(在大多数解释器上),该值是预先加载到内存中的,因此在第一个示例中,a是bHank you@JacquesGaudin!这让我现在有了一些理解。是否进行了这种优化并不能保证。您应该停止思考这个问题,有时
is
会返回
True
,而其他时候则不会。如果您想确保它返回
True
,只需执行以下操作:
b=a
b=tuple(a)
(如果将一个元组作为参数传递,则
tuple
调用将返回对参数的引用。)我重新打开此操作是因为dup目标没有解决此问题的要点,即,如果易变性对标识有影响。在上面提到的示例(元组)中:a[1]是b[1]应该为True,为什么它返回False?@Ram为什么你认为它应该返回True,它们是两个独立的对象(整数),但具有相同的值(不是id)。注意它们不少于256。是的,同意。我认为只有小于256的整数才会返回ids()true。python解释器中任何大于256的整数都有自己的id空间,值都是相同的。所有小的8位数字都引用内存中相同的对象,这是一个CPython实现细节,不应依赖于任何reason@Ram我相信你是从错误的角度看待这种情况的。您应该问问自己,为什么它会为
a[0]
b[0]
返回
True
,而不是为
a[1]
b[1]
返回
False
。看看你是否想要更多的细节。
>>> 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)
>>>