BAE BAE - 3 months ago 12
Python Question

python: how to explain the following codes

Tested on my local machine:

Python 2.7.3 (default, Jun 22 2015, 19:33:41)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> q=[2,3]
>>> p=[1,q,4]
>>> p[1].append('test')
>>> q
[2, 3, 'test']
>>> hex(id(q))
'0x7fabfa5c2b90'
>>>
>>>
>>> hex(id(p))
'0x7fabfa5c2b48'
>>> hex(id(p[1]))
'0x7fabfa5c2b90'
>>>
>>>
>>> p.append(q)
>>> p
[1, [2, 3, 'test'], 4, [2, 3, 'test']]
>>> p[1].append('test2')
>>> p
[1, [2, 3, 'test', 'test2'], 4, [2, 3, 'test', 'test2']]
>>>


At beginning, I thought when generating p, a copy of q is copied into p.

Any document can help understand the above behaviour? I have no idea why python did this? and In which cases, this behaviour will happen?

Thanks

Answer

When you append q to p, you are not creating a copy of q, you are actually appending a reference to the object that the name q currently points to. Therefore, when you append to q (or in this case p[1], which points to the same object), it will append to the single object that those two references point to. If you want to insert a copy of q, you can use slicing like so:

p=[1,q[:],4]

or

p.append(q[:])

This will create a new anonymous list that you can append to without affecting the original or any other reference to that same object that q points to.

Here's an example:

>>> q = [2, 3]
>>> p = [1, q[:], 4]      # include a copy of q using [:]
>>> p[1].append('test')   # append to copy
>>> p
[1, [2, 3, 'test'], 4]    # 'test' is in p[1]
>>> q 
[2, 3]                    # but not in q
>>> p = [1, q, 4]         # include q itself in p (no [:])
>>> p[1].append('test')
>>> p
[1, [2, 3, 'test'], 4]    # test appears in p[1]
>>> q
[2, 3, 'test']            # and also in q

See the docs for lists here

Comments