0

I initialized a 2d array and set all the elements to False. Then in my code I want to switch certain elements to True if conditions are met. However, arr[i][j] = True sets ALL j elements in arr to True. Why is that, and what is the correct syntax?

arr = [[False]*3]*4
print(arr)
arr[1][2] = True
print(arr)

This gives

[[False, False, False], [False, False, False], [False, False, False], [False, False, False]]

which is what we expected, and then

[[False, False, True], [False, False, True], [False, False, True], [False, False, True]]

where all the arr[i][2]'s are set to True, instead of just arr[1][2]

petezurich
  • 9,280
  • 9
  • 43
  • 57
Jim
  • 11
  • Hi, the outer list contains 4 elements that are all the same instance, so modifying one will cause the other elements to reflect the change as well. `[False]*3` is a single list of 3 elements which is then inserted 4 times into the outer array. – jspcal May 01 '19 at 20:51
  • Because he only modified the last element of the sublist - `arr[1][2] = True`. – jspcal May 01 '19 at 20:57

1 Answers1

0

You should not create multidimensional arrays with the * syntax. What happens is that [False]*3 is evaluated first, creating a list with three elements that each refer to the immutable value False, but then the outer []*4 creates a list of four elements that all refer to the same three-element list. Instead, create an empty list, and use a loop to repeatedly append [False]*3 to the list - that will reevaluate [False]*3 every time, creating distinct inner lists.

Aasmund Eldhuset
  • 37,289
  • 4
  • 68
  • 81
  • The most compact one I know about is to use a comprehension: `[[False] * 3 for i in range(4)]` – Aasmund Eldhuset May 01 '19 at 20:53
  • Thank you! and this applies to everything, lets say arr = [[1]*3]*4 as well, correct? Not just bool. This should also be written as arr = [[1]*3 for _ in range(4)]? didn't expect that, as arr = [1]*3 works fine – Jim May 01 '19 at 20:57
  • 1
    `[1] * 3` also creates three references to the _same_ `1`. But numbers are immutable. If they weren't, you'd see that changing one would change all. What you're changing when you do `arr[0] = 3` is not the number itself, but what the array's element 0 refers to. – Aasmund Eldhuset May 01 '19 at 21:03
  • 1
    `arr[0][0]` also changes what element 0 of the innermost array refers to (so the other elements in the inner array don't change), but all the elements of the outer array refer to the same inner array. – Aasmund Eldhuset May 01 '19 at 21:04