2

I am trying to loop through my list of lists, and change the values. I want this to print [['1','2'],['3','4']]. but it prints [['3','4'],['3','4']]. Can anyone please explain why this is happening? When I put a print statement, count increase for each iterations.

edit: it works if I manually create a list like [[0,0],[0,0]]. So what is the [[0]*2]*2 doing differently? They both look like 2d lists.

class Sudoku:
    def __init__(self):
        self.board=[[0]*2]*2

s=Sudoku()
count=1
for i in range(2):
   for j in range(2):
       s.board[i][j]=count
       count+=1
print(s.board)
U13-Forward
  • 69,221
  • 14
  • 89
  • 114
Eric Smith
  • 313
  • 1
  • 2
  • 8

1 Answers1

4

[0]*2 evaluates to the list [0, 0]. Let's call it Bob.

[[0]*2]*2 is then [Bob, Bob] - a list of two references to the same Bob. You change Bob, Bob changes.

In order to be able to change the two sub-arrays independently, they must not be coreferent - which means you can't use * to copy the reference to the inner mutable object (Bob):

[[0]*2 for i in range(2)]

This will construct Bob for i == 0, and Bob's twin brother (Rob?) at i == 1. You change Bob, Rob doesn't care.

Note that this doesn't apply to the zero in [0]*2: a number is not a mutable type, there's nothing you can do to a zero except replace it entirely.

it works if I manually create a list like [[0,0],[0,0]]. So what is the [[0]*2]*2 doing differently?

OK, manual experiment time.

bob = [0, 0]                 # our Bob.
rob = [0, 0]                 # Rob _looks_ the same, but _is not_ the same
bob_and_bob = [bob, bob]     # [[0, 0]]*2
bob_and_rob = [bob, rob]     # [[0, 0], [0, 0]]

bob[0] = 1                   # we change Bob...
bob_and_bob                  # => [[1, 0], [1, 0]]  Bob changes.
bob_and_rob                  # => [[1, 0], [0, 0]]  Rob doesn't care.
Amadan
  • 191,408
  • 23
  • 240
  • 301
  • You can also look at `id(s.board[0])` and `id(s.board[1])` - both rows are the same object in memory. – Marius Oct 19 '18 at 05:02