views:

476

answers:

3

I needed to create a list of lists in Python, so I typed the following:

myList = [[1] * 4] * 3

The list looked like this:

[[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]]  

Then I changed one of the innermost values:

myList[0][0] = 5

Now my list looks like this:

[[5, 1, 1, 1], [5, 1, 1, 1], [5, 1, 1, 1]]  

which is not what I wanted or expected. Can someone please explain what's going on, and how to get around it?

+8  A: 
 [[1] * 4] * 3

or even

 [[1, 1, 1, 1]] * 3

Creates a list that references the internal [1,1,1,1] 3 times - not three copies of the inner list, so any time you modify the list (in any position), you'll see the change three times.

It's the same as this example:

>>> inner = [1,1,1,1]
>>> outer = [inner]*3
>>> outer
[[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]]
>>> inner[0] = 5
>>> outer
[[5, 1, 1, 1], [5, 1, 1, 1], [5, 1, 1, 1]]

where it's probably a little less surprising.

Blair Conrad
You can use the "is" operator to discover this. ls[0] is ls[1] returns True.
mipadi
+23  A: 

When you write [x]*3 you get, essentially, the list [x, x, x]. That is, a list with 3 references to x. When you then change x all three references are changed.

To fix it, you need to make sure that you create a new list at each position. One way to do it is

[[1]*4 for n in range(3)]
CAdaker
Thanks for the explanation and the workaround. I am still surprised though that the outer list ends up holding three references to an anonymous inner list.
Charles Anderson
+6  A: 

Actually, this is exactly what you would expect. Let's decompose what is happening here:

You write

lst = [[1] * 4] * 3

This is equivalent to:

lst1 = [1]*4
lst = [lst1]*3

This means lst is a list with 3 elements all pointing to lst1. This means the two following lines are equivalent:

lst[0][0] = 5
lst1[0] = 5

As lst[0] is nothing but lst1.

To obtain the desired behavior, you can use list comprehension:

lst = [ [1]*4 for n in xrange(3) ]

In this case, the expression is re-evaluated for each n, leading to a different list.

PierreBdR