Reputation: 8936
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
Upvotes: 0
Views: 59
Reputation: 4469
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
Upvotes: 3
Reputation: 306
If you are new to Python you may run into issues like this.
In Python if you say
a = [10]
And then say
b = a
What happens? b gets the value of a, but also any change in a will make the similar change in b, because instead of just copying the value "b" is pointed towards "a" (that means changes in a will reflect in b as well) That is the reason why you are facing that issue.
In case you don't want this you can use copy module in python
from copy import copy
b = copy(a)
Now even though you change the value of "a", "b" value will be same.
For any reference regarding the same topic
Upvotes: 1
Reputation: 4903
Well, I can explain. Your p
keeps reference to q
and you cannot change that. That's all. So if you will edit p[1]
, then basically it modifies q
, because going there through reference.
Any document can help understand the above behaviour? https://docs.python.org/2/reference/datamodel.html
I have no idea why python did this?
To have two ways of doing things.
Based on reference to object (you don't pass a copy of q
to p
, just only reference):
>>> q=[2,3]
>>> p=[1,q,4]
>>> p[1].append('test')
>>> q
[2, 3, 'test']
and without (you pass a copy of q
to p
, not reference):
>>> q=[2,3]
>>> p=[1,q[:],4]
>>> p[1].append('test')
>>> q
[2, 3]
In which cases, this behaviour will happen?
I think example above shows it.
Upvotes: 1