nested list set broadcasts?

Alright, I thought I understood python pretty well, but clearly there is a big gap in my understanding of nested lists and their indexing.

Imagine we create a "matrix" (nested lists, where each list represent a row) filled with say 0. I want to iterate over each row and column and set that item. This task would be better done with numpy arrays, but stay with me for now.

a = [[0]*4]*4
print(a)
# prints [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]

a[0][0] = 10
print(a)
# prints [[10, 0, 0, 0], [10, 0, 0, 0], [10, 0, 0, 0], [10, 0, 0, 0]]

Why has the first element in each inner list (row) been set to 10? I expected the first element in the first list to be 10.

1 answer

  • answered 2021-06-19 19:15 Matthew Hamilton

    This is because each list you see all refer to the same object in memory. Using *4 is generally discouraged for mutable objects for precisely this reason. Using this code will get you the behavior you expect

    a = [[0 for j in range(4)] for i in range(4)]
    print(a)
    # prints [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
    
    a[0][0] = 10
    print(a)
    # prints [[10, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]