1

I'm trying to modify the list of lists:

list = [['0', '0', '0', '0', '0', '0'], ['0', '0', '0', '0', '0', '0'], ['0', '0', '0', '0', '0', '0'], ['0', '0', '0', '0', '0', '0'], ['0', '0', '0', '0', '0', '0']]

in particular when I assign list[0][1]='X', list is now:

[['0', 'X', '0', '0', '0', '0'], ['0', 'X', '0', '0', '0', '0'], ['0', 'X', '0', '0', '0', '0'], ['0', 'X', '0', '0', '0', '0'], ['0', 'X', '0', '0', '0', '0']]

instead of just reassigning the second element of the first sub list, it reassigns the first element of every sub list. I don't understand why this is happening. Does anyone know?

Javier Rabba
  • 13
  • 1
  • 3
  • This is because of how you created `list`. Please show how you did that. – anon582847382 Nov 04 '14 at 21:34
  • Because your `list` contains multiple references to the same other list. – khelwood Nov 04 '14 at 21:35
  • This is a dup of a few dozen questions on SO (I'm searching for the best one), plus [an entry in the official Python FAQ](https://docs.python.org/3/faq/programming.html#how-do-i-create-a-multidimensional-list). – abarnert Nov 04 '14 at 21:38
  • [Two-dimensional list wrongly assigning values in python](http://stackoverflow.com/questions/18667942/two-dimensional-list-wrongly-assigning-values-in-python/18667977#18667977) is another nice one. – abarnert Nov 04 '14 at 21:40

1 Answers1

3

You must have created list like so:

list = [['0', '0', '0', '0', '0', '0']] * 5

Doing this creates a list with five references to the same list object:

>>> list = [['0', '0', '0', '0', '0', '0']] * 5
>>> id(list[0])
27391360
>>> id(list[1])
27391360
>>> id(list[2])
27391360
>>>

So, when you modify one sublist, they all get changed.


To fix the problem, use a list comprehension instead:

lst = [['0', '0', '0', '0', '0', '0'] for _ in range(5)]

Unlike your current code, this solution will create a list with five unique sublists. Consequentially, changing one will not affect the others.

Also, I changed the name of your list to lst to avoid shadowing the built-in. You should never create a name that is the same as a built-in.


Note that you could also write:

lst = [['0'] * 6 for _ in range(5)]

Doing ['0'] * 6 is not a problem here because strings are immutable objects in Python. So, ['0'] * 6 creates a list with six unique string objects. Lists however are mutable objects and therefore cannot be created like this.

  • `lst = [ 6*['0'] for _ in range(5) ]` more succinctly. – khelwood Nov 04 '14 at 21:37
  • @khelwood - Good idea. I'll mention it. –  Nov 04 '14 at 21:38
  • Thanks guys, problem solved. One question though. if the list ['0', '0', '0', '0', '0', '0'] is not always the same but it is stored in some variable a, how do you rewrite the part of the "for _ in ..."? – Javier Rabba Nov 04 '14 at 22:50
  • @JavierRabba - You can make a copy of the list by putting it in `list`: `lst = [list(a) for _ in range(5)]`. Although I personally would probably use slice notation: `lst = [a[:] for _ in range(5)]`. It may not be as readable to some, but it is more concise and generally faster. –  Nov 04 '14 at 22:51