Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: copying a list within a list

Tags:

python

list

Hoping someone can help me here.

I'm very new to Python, and I'm trying to work out what I'm doing wrong.

I've already searched and found out that that Python variables can be linked so that changing one changes the other, and I have done numerous tests with the id() function to get to grips with this concept. But I seem to have found an exception I'm hoping someone can explain...

firstly, the following works as expected to make a independent copy of a list.

>>> a = [0,0]
>>> b = a[:]
>>> print a is b
False
>>> b[0]=1
>>> print a
[0,0]
>>> print b
[1,0]

But if I change this slightly so that a is list within a list it changes...

>>> a = [[0,0],[0,0]]
>>> b = a[:]
>>> print a is b
False
>>> b[0][0]=1
>>> print a
[[1, 0], [0, 0]]
>>> print b
[[1, 0], [0, 0]]

Now we see that any update of b will also apply to a, but yet the result of print a is b returns False?? I've check this against id() as well, everything says they are independent of each other, but when I update one the same applies to the other??

Can anyone explain this??

Noting I'm running these of http://labs.codecademy.com/#:workspace, so my first thought is that it's just a bug on their site, but I don't know?

EDIT:

THANK YOU ALL for the great answers so far. That was fast! I know this has probably been asked before but it was difficult thing to search for.

Since all the answers are correct, I'll wait a day before marking. whoever has the most +1's will get the mark :)

like image 585
Skytunnel Avatar asked Jul 05 '13 21:07

Skytunnel


2 Answers

b = a[:] creates a shallow copy of a, so changing the mutable lists within b still effects those same lists in a.

In other words, a and b do not point to the same list (which is why a is not b), but rather to two different lists which both contain the same two lists. You change one of these lists via b[0][0] = 1 and that change shows up in a.

You mentioned that you were playing around with id(), so take a look at this:

>>> a = [[0,0],[0,0]]
>>> b = a[:]
>>> id(a)
2917280                    # <----+
>>> id(b)                  #      |----- different!
2771584                    # <----+
>>> id(a[0]), id(a[1])
(2917320, 2917360)         # <----+
>>> id(b[0]), id(b[1])     #      |----- same!
(2917320, 2917360)         # <----+
like image 101
arshajii Avatar answered Oct 08 '22 00:10

arshajii


You need to make a deepcopy of your list. a[:] only makes a shallow copy - see docs

You can use copy.deepcopy function:

>>> import copy
>>> a = [[0,0],[0,0]]
>>> b = copy.deepcopy(a)
>>> b
[[0, 0], [0, 0]]
>>> b[0][0]=1
>>> a
[[0, 0], [0, 0]]
like image 39
Rohit Jain Avatar answered Oct 07 '22 23:10

Rohit Jain