Python 混淆别名

Python 混淆别名,python,aliasing,Python,Aliasing,我有以下代码可以按预期工作: a = [1, 2, 3, 4] b = a >>> b is a True 如果我稍微改变一下,它仍然有效: a = [1, 2, 3, 4] b = a[2] * 2 >>> b is a[2] * 2 True 现在的问题是: a = [1, 2, 3, 4] b = a * 2 >>> b is a * 2 False 有人能给我解释一下为什么它返回False,而b是a[2]*2返回T

我有以下代码可以按预期工作:

a = [1, 2, 3, 4]
b = a

>>> b is a
True
如果我稍微改变一下,它仍然有效:

a = [1, 2, 3, 4]
b = a[2] * 2

>>> b is a[2] * 2
True
现在的问题是:

a = [1, 2, 3, 4]
b = a * 2

>>> b is a * 2
False    

有人能给我解释一下为什么它返回False,而
b是a[2]*2
返回True吗?

a*2构造一个新的列表,而整数本身具有标识

>>> type(a[2] * 2)
<type 'int'>
>>> type(a * 2)
<type 'list'>
>类型(a[2]*2)
>>>类型(a*2)

a*2构造一个新列表,而整数本身具有标识

>>> type(a[2] * 2)
<type 'int'>
>>> type(a * 2)
<type 'list'>
>类型(a[2]*2)
>>>类型(a*2)

a
是一个列表时,
a*2
创建一个新的列表实例。如果调用
a*2
两次,就会创建两个新的列表实例——这就是
b是a*2
的原因

对于
b,得到
True
的原因是[2]*2
是对缓存小整数的CPython的优化。由于整数在Python中是不可变的,所以实际上,无论是获得新实例还是缓存实例,对于小整数,如果再次命中相同的整数,Python都会返回缓存版本。也尝试

>>> a = [1, 2, 300, 4]
>>> b = a[2] * 2
>>> b is a[2] * 2
False

a
是一个列表时,
a*2
创建一个新的列表实例。如果调用
a*2
两次,就会创建两个新的列表实例——这就是
b是a*2
的原因

对于
b,得到
True
的原因是[2]*2
是对缓存小整数的CPython的优化。由于整数在Python中是不可变的,所以实际上,无论是获得新实例还是缓存实例,对于小整数,如果再次命中相同的整数,Python都会返回缓存版本。也尝试

>>> a = [1, 2, 300, 4]
>>> b = a[2] * 2
>>> b is a[2] * 2
False

相同的列表在比较时并不相等,除非它们引用相同的列表。列表具有相同的值并不意味着它们在内存中引用相同的列表

例如:

>>> a = [1,2,3]
>>> id(a) # memory location list a references
161267628
>>> b = [1,2,3]
>>> id(b) # memory location list b references, a different memory location than list a
161276396
>>> a == b 
True
>>> a is b
False
>>> c = a # by this method of assignment; c points to the same point that a does;
# hence changes to a and changes to c, will change both.
>>> id(c) # memory location that c references; this is the same as where a points.
161267628
>>> a is c
True
>>> c.append(4)
>>> print a
[1, 2, 3, 4]
>>> print b
[1, 2, 3]
>>> print c
[1, 2, 3, 4]
>>> d = a[:] # this just copies the values in a to d.  
>>> id(d)
161277036

这说明它们指向不同的内存位置是有道理的,因为如果您想说更改第一个列表(例如将
4
附加到
a
末尾)不修改
b
,如果
a
b
指向内存中的同一位置,这是不可能的。

相同的列表在比较时并不等价,除非它们引用相同的列表。列表具有相同的值并不意味着它们在内存中引用相同的列表

例如:

>>> a = [1,2,3]
>>> id(a) # memory location list a references
161267628
>>> b = [1,2,3]
>>> id(b) # memory location list b references, a different memory location than list a
161276396
>>> a == b 
True
>>> a is b
False
>>> c = a # by this method of assignment; c points to the same point that a does;
# hence changes to a and changes to c, will change both.
>>> id(c) # memory location that c references; this is the same as where a points.
161267628
>>> a is c
True
>>> c.append(4)
>>> print a
[1, 2, 3, 4]
>>> print b
[1, 2, 3]
>>> print c
[1, 2, 3, 4]
>>> d = a[:] # this just copies the values in a to d.  
>>> id(d)
161277036

这说明它们指向不同的内存位置是有道理的,因为如果您想说更改第一个列表(例如将
4
附加到
a
末尾)不修改
b
,如果
a
b
指向内存中的同一位置,这是不可能的。

具有相同值的两个整数可能不是相同的实例——请参见我在回答中给出的示例。事实确实如此。2**32是2**32=>False。具有相同值的两个整数可能不是相同的实例——请参见我在回答中给出的示例。事实确实如此。2**32是2**32=>False。当然,底线是不要使用
is
,除非你真的想要;使用
==
进行数值比较。很好的解释@安德鲁,我明白用
==
代替
的好处是
。当然,底线是除非你真的想,否则不要用
;使用
==
进行数值比较。很好的解释@Andrew,我肯定看到了使用
==
而不是
的好处。我喜欢你使用内存位置,因为它帮助我了解python在赋值中实际做了什么。我有一种感觉,将来我会大量使用
id()
。我喜欢您对内存位置的使用,因为它帮助我了解python对赋值的实际操作。我有一种感觉,将来我会大量使用
id()。