2

I want to understand small snippet here in python:

>>> x = ['foo', [1,2,3], 10.4] >>> y = list(x) >>> y[0] 'foo' >>> y[0] = "fooooooo" >>> y[1] [1, 2, 3] >>> y[1][0]=4 >>> print x ['foo', [4, 2, 3], 10.4] >>> print y ['fooooooo', [4, 2, 3], 10.4] >>> z = ['foo', [1,2,3], 10.4] >>> x = ['foo', [1,2,3], 10.4] >>> y = list(x) >>> y[0] = "fooooooo" >>> y[1] [1, 2, 3] >>> y[1][0]=4 >>> print x ['foo', [4, 2, 3], 10.4] >>> print y ['fooooooo', [4, 2, 3], 10.4] >>> print z ['foo', [1, 2, 3], 10.4] >>> y = list(z) >>> y[1][0]=6 >>> print y ['foo', [6, 2, 3], 10.4] >>> y = list(z) >>> print z ['foo', [6, 2, 3], 10.4] >>> print x ['foo', [4, 2, 3], 10.4] 

How this works. if change the list element of y its getting reflecting to x. It may be very basic of python but still i am not getting hold on this

3 Answers 3

4
y = list(x) 

Above statement creates a shallow copy of the list x.

From the documentation:

A shallow copy constructs a new compound object and then (to the extent possible) inserts references into it to the objects found in the original.

In here, you do get a new object y but since the list inside it is a mutable object, you get the reference to the original object. And, if you keep creating these shallow copies the list object will be shared among all the copies.

You can check it using id:

>>> id(x) 140183460314288 >>> id(y) 140183460372992 # this is different from y >>> id(x[1]) 140183460314864 >>> id(y[1]) # this is same as x[1] 140183460314864 >>> y1 = list(y) # another shallow copy from y >>> id(y1[1]) 140183460314864 # this is still same 

If you expect a behavior where you do need to modify the contents of y without affecting x, you need to perform deepcopy:

>>> >>> from copy import deepcopy >>> z = deepcopy(x) >>> id(z[1]) 140183460405400 # this is different now because of deepcopy 

You can see that this id is different than id(x[1]), and now if you try to modify the contents they won't be reflected in x.

Sign up to request clarification or add additional context in comments.

3 Comments

Ok but why its not changed for y[0] = "fooooooo" in x
Because you are doing an assignment and since string is immutable it will create a new object. You can check the value of id(y[0])) after changing its value, it will be different.
because strings are non mutable: try s='abc' then s[0]='d', you'll get an error. When you copy x you get a new string (copy), so x[0] and y[0] are 2 different strings, while x[1] and y[1] or 2 references to the same (mutable) list.
3

I'm guessing the only thing you're confused by is the fact that setting the elements of the nested list of one variable will change the nested lists of all other variables. The reason is simple: Python is using the same nested list (as in, the exact same memory) in each variable. When you say y = list(x), Python copies all of the atomic elements of x into y but merely copies a reference to the nested list. Since the same nested list is used everywhere, modifying it one place modifies it everywhere.

You can also see similar behavior by playing around with l1 = [0]*3 and l2 = [[0]]*3; the differences between how l1 and l2 behave are another example of the behavior you're observing.

Comments

1
>>> x = ['foo', [1,2,3], 10.4] >>> y = list(x) 

y is a copy of x. y[1] contains a copy of the reference in x to the list [1,2,3]. So y[1] and x[1] are 2 references to the same list.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.