BAE
BAE

Reputation: 8936

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

Upvotes: 0

Views: 59

Answers (3)

Will
Will

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

Neeraj Komuravalli
Neeraj Komuravalli

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

turkus
turkus

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

Related Questions