36

I have this 7x7 two-dimensional array:

l=[[1, 1, 1, 1, 1, 1, 1],
  [1, 0, 2, 0, 0, 0, 1],
  [1, 0, 0, 0, 0, 0, 1],
  [1, 0, 0, 0, 0, 0, 1],
  [1, 0, 0, 0, 0, 0, 1],
  [1, 0, 0, 0, 0, 0, 1],
  [1, 1, 1, 1, 1, 1, 1]]

As you can see, l[1][2]=2. When I print it, the element is printed correctly. No problem here. But when I try to change it from "2" to "3" or any other number, the program changes all the elements on that column (in this case the 3rd column) except for the first and last ones. For example, if I type this code:

l[1][2]=5

and then print the two-dimensional array, I get this:

l=[[1, 1, 1, 1, 1, 1, 1],
  [1, 0, 5, 0, 0, 0, 1],
  [1, 0, 5, 0, 0, 0, 1],
  [1, 0, 5, 0, 0, 0, 1],
  [1, 0, 5, 0, 0, 0, 1],
  [1, 0, 5, 0, 0, 0, 1],
  [1, 1, 1, 1, 1, 1, 1]]

This happens with every element that I choose. Instead of changing only that element, it changes the entire column. Does anyone know what might be the problem? Thank you!

Joker
  • 371
  • 1
  • 4
  • 6
  • 1
    I cannot reproduce it. Could you please run all this yourself in the python interpreter? Which python are you using? – László Papp Jan 10 '14 at 04:21
  • This makes no sense, even if you have a NumPy matrix or multiple references to the same list. Could you please show us an actual interpreter session? – user2357112 Jan 10 '14 at 04:23
  • 2
    Can you show us how you actually construct the list to start? I assume that you accidentally are storing multiple references to the same list. – mgilson Jan 10 '14 at 04:23
  • @mgilson: Likely, but that still wouldn't produce the output shown. This is probably because the output shown isn't what the OP actually got. – user2357112 Jan 10 '14 at 04:25
  • @user2357112 -- Yes, I highly doubt that the output is what OP actually got. If not for the first row, the list could have been constructed like `l = [a, b, b, b, b, b, c]` ... – mgilson Jan 10 '14 at 04:32
  • I tried to do the same thing in a new file and it worked, as expected. So the problem is with the program that I'm working on. The list is defined like this : l=[[0]*w]*h where w, h are variables. At first it's a wxh matrix containing only zeroes. Then I changed the margins to element "1". The same thing I did in the new file where it worked fine. I don't know if posting the entire code of the program here would help. – Joker Jan 10 '14 at 04:37
  • I noticed now that I made a mistake in writing the output. The first line and the last remain unchanged. Only the lines in the middle are changed. Exactly like @mgilson suggested. I understand now what the problem is and I solved it using his answer. Thank you. – Joker Jan 10 '14 at 04:58

2 Answers2

66

I'm gonna take a stab at this one even though the behavior you describe (as you've described it) isn't possible.

If you create a list, you need to make sure that each sublist is a different list. Consider:

a = []
b = [a, a]

Here I've created a list where both of the sublists are the exact same list. If I change one, it will show up in both. e.g.:

>>> a = []
>>> b = [a, a]
>>> b[0].append(1)
>>> b
[[1], [1]]

you'll frequently see this behavior with a list initialized using the * operator:

a = [[None]*7]*7

e.g.

>>> a = [[None]*7]*7
>>> a
[[None, None, None, None, None, None, None], [None, None, None, None, None, None, None], [None, None, None, None, None, None, None], [None, None, None, None, None, None, None], [None, None, None, None, None, None, None], [None, None, None, None, None, None, None], [None, None, None, None, None, None, None]]
>>> a[0][1] = 3
>>> a
[[None, 3, None, None, None, None, None], [None, 3, None, None, None, None, None], [None, 3, None, None, None, None, None], [None, 3, None, None, None, None, None], [None, 3, None, None, None, None, None], [None, 3, None, None, None, None, None], [None, 3, None, None, None, None, None]]

The fix is to not use the * 7 on the outer list (the inner list is OK since None is immutable):

a = [[None]*7 for _ in range(7)]

e.g.:

>>> a = [[None]*7 for _ in range(7)]
>>> a[0][1] = 3
>>> a
[[None, 3, None, None, None, None, None], [None, None, None, None, None, None, None], [None, None, None, None, None, None, None], [None, None, None, None, None, None, None], [None, None, None, None, None, None, None], [None, None, None, None, None, None, None], [None, None, None, None, None, None, None]]
mgilson
  • 300,191
  • 65
  • 633
  • 696
3

You've constructed your list wrong.

The middle items are all referring to the same list, so updating one causes the change to be reflected in the others

If you show the code you're using to construct the list, I can show you how to fix it.

Alternatively

l = [sublist[:] for sublist in l]

before you begin modifying the lists will decouple all those into new lists

John La Rooy
  • 295,403
  • 53
  • 369
  • 502