15

I have a list of List say mysolution:

>>>mySolution
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
>>> mySolution[0][0] = 1    
>>> mySolution
[[1, 0, 0, 0], [1, 0, 0, 0], [1, 0, 0, 0], [1, 0, 0, 0]]

Intended output:

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

why is it that all the 1st elements in my list of list's is being changed to 1? I would only like to change the first element of the first list to 1.

Carcigenicate
  • 43,494
  • 9
  • 68
  • 117
Pavan
  • 2,715
  • 4
  • 18
  • 19
  • 7
    Oh that pesky `n * list` operator! I honestly wouldn't mind if it threw an exception when mutable types were detected .. – user2246674 Sep 22 '13 at 17:36

4 Answers4

21

What matters is how you created your original mysolution list. As it seems, it contains four times the same list which is why changing it once will make it change in all four locations.

To initialize independent zero-filled lists like that, you can do the following:

mysolution = [[0] * 4 for i in range(4)]
poke
  • 369,085
  • 72
  • 557
  • 602
8

It's quite possible that you created the list like this:

mySolution = [0]*4
mySolution = [mySolution]*4

Or equivalently:

mySolution = [[0]*4]*4

Either of the above snippets will create a list with four sublists which are copies of the exact, same sublist, so any modification on one sublist will be reflected on the others - they're one and the same. The solution is to create four different sublists:

mySolution = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]

Or a bit shorter:

mySolution = [[0]*4 for _ in xrange(4)]
Óscar López
  • 232,561
  • 37
  • 312
  • 386
3

Because all the contained lists are actually the same list. When you do:

l = [0, 0, 0, 0]
my_solution = [l, l, l]

Then, my_solution[0], my_solution[1], and my_solution[2] are references to the same object (l).

If you modify the list in one location, it changes everywhere. That is because lists are mutable objects.

Instead, use multiple lists:

l1 = [0, 0, 0, 0]
l2 = [0, 0, 0, 0]
l3 = [0, 0, 0, 0]
my_solution = [l1, l2, l3]

Which will work as intended.

Thomas Orozco
  • 53,284
  • 11
  • 113
  • 116
3

please note that this is doing fine:

mySolution = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
mySolution[0][0] = 1    
print mySolution

>>> 
[[1, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]

it all depends on how you initialized your solution. this

mySolution = [[0, 0, 0, 0]]*4
mySolution[0][0] = 1    
print mySolution

gives

>>> 
[[1, 0, 0, 0], [1, 0, 0, 0], [1, 0, 0, 0], [1, 0, 0, 0]]
>>> 

because here each array [0, 0, 0, 0] in mySolution is a copy of initialization array [0, 0, 0, 0] in [[0, 0, 0, 0]]*4. if you change first element of first array, copy of it also change.

with this initialization mySolution = [[0, 0, 0, 0] for x in range(4)] you are not copying the array but appending [0,0,0,0] four times, giving the result that you are expecting.

kiriloff
  • 25,609
  • 37
  • 148
  • 229