开发者

Messing around with Aliasing

I have the following code that works as expected:

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

>>> b is a
True

if I change it up a little it still works:

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

>>> b is a[2] * 2
True

Now the problem:

开发者_JAVA技巧a = [1, 2, 3, 4]
b = a * 2

>>> b is a * 2
False    

Can someone please explain to me why this returns False, while b is a[2] * 2 returns True?


When a is a list, a * 2 creates a new list instance. If you call a * 2 twice, you create two new list instances -- that's why b is a * 2 yields False.

The reason that you get True for b is a[2] * 2 is an optimisation of CPython that caches small integers. Since integers are immutable in Python, it actually does not matter if you get a new instance or a cached one, and for small integers, Python returns a cached version if you hit the same integer again. Also try

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


Identical lists aren't equivalent when compared is unless they reference the same list. Just because the lists have the same values doesn't mean they reference the same list in memory.

E.g.,

>>> 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

This makes sense that they point to different memory locations, because if you may want to say change the first list (like append 4 to the end a) without modifying b which wouldn't be possible if a and b pointed to the same location in memory.


a * 2 constructs a new list, while an integer has identity with itself.

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜