2

I'm trying to make a "target", a copy of "grid." I don't see why this code does not work.

grid = [[randint(0, 1), randint(0, 1), randint(0, 1)],
        [randint(0, 1), randint(0, 1), randint(0, 1)],
        [randint(0, 1), randint(0, 1), randint(0, 1)]]

target = [[0, 0, 0]] * 3
for x in range(3):
    for y in range(3):
        target[x][y] = grid[x][y]

print target
print grid

Here's a result:

[[0, 1, 0], [0, 1, 0], [0, 1, 0]]
[[1, 0, 0], [0, 1, 1], [0, 1, 0]]
El Bert
  • 2,958
  • 1
  • 28
  • 36
Ian Tan
  • 23
  • 3

1 Answers1

5

This part:

target = [[0, 0, 0]] * 3

Creates a list with the same list repeated 3 times. So changes to one item actually reflects in all (they are the same object). What you want is to create a list three times:

target = [[0, 0, 0] for _ in range(3)]

You should only use the star operator on list (or list multiplication) with immutable objects (if at all), which do not have this problem since you can't change their states.

Don't forget you can use (x[:] is used to create a shallow copy of a list named x, just like list(x)):

grid = [x[:] for x in target]

Or even more generally with copy.deepcopy:

from copy import deepcopy
grid = deepcopy(target)
Reut Sharabani
  • 30,449
  • 6
  • 70
  • 88
  • Wow. For a novice like me that's very subtle thing to keep in mind. Thanks! – Ian Tan Mar 16 '15 at 23:55
  • 1
    @IanTan You may be unfamiliar with the `x[:]` syntax then, it's just a method to create a copy of the list -- [here are alternative syntaxes](http://stackoverflow.com/questions/2612802/how-to-clone-or-copy-a-list-in-python) – jedwards Mar 17 '15 at 00:00
  • Thanks. This is very convenient. – Ian Tan Mar 17 '15 at 00:05
  • The other way to copy a list is x = list (yourlist) – Fred Mitchell Mar 17 '15 at 00:28
  • @FredMitchell this creates a shallow copy so you're still concerned with what you're copying. `deepcopy` iteratively deep-copies all items in more complex nested types such as `dict`s or `list`s – Reut Sharabani Mar 17 '15 at 00:33