0

I hope to set up a matrix/list through for loop but I observed different results between 1D list and 2D list of the same method. I know this is a stupid way to create a list through for loop but could anyone give me a hint what caused the difference please?

m = [[0] * 4] * 4
print m
m[0] = range(4)
for i in range(4):
    m[i][0] = i
print m

And the result is:

[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
[[0, 1, 2, 3], [3, 0, 0, 0], [3, 0, 0, 0], [3, 0, 0, 0]]

I was expecting to be [[0, 1, 2, 3], [1, 0, 0, 0], [2, 0, 0, 0], [3, 0, 0, 0]]. However it worked find in 1D list as below

tmp = [0,0,0,0]
for i in range(4):
    tmp[i] = i
print tmp

It printed [0,1,2,3] as I expected.

sid8491
  • 6,622
  • 6
  • 38
  • 64
evehsu
  • 39
  • 4
  • 1
    Noooo, please don't use `*` on nested lists, it's only duplicating the references. – cs95 Dec 27 '17 at 09:24

2 Answers2

1

Change the first line to get:

#m = [[0] * 4] * 4
m = [([0] * 4) for _ in range(4)]
print m
m[0] = range(4)
for i in range(4):
    m[i][0] = i
print m

What happened before was that you were creating four copies of the same list. Each copy looks to the same memory spaces. Python does this to conserve memory. So each time you write to one of the lists, you are in fact writing to all of them, and because the last value you write is 3, that's the value you get in all of the lists.

Ulf Aslak
  • 7,876
  • 4
  • 34
  • 56
0

When you are doing m = [[0] * 4] * 4, you are creating a 2D matrix of all zeros. In other words, a list of four [0, 0, 0, 0] lists. Now, with m[0] = range(4), you are setting the first inner list to be [0,1,2,3]. Now when you do,

for i in range(4):
    m[i][0] = i

you are expecting for each inner lists first element to be changed. This is one of python's quicks creep in. Object reference. When you initially create the 2D list, you are essentially referencing one list from each of the four indices. Then you replace m[0] to a separate list here: m[0] = range(4). However, all there indices refer to the same list object [0, 0, 0, 0]. And when the loop eventually finishes, value of i is 3 and that is assigned to the first element of the list. And since in index 1, 2 and 3 of m was referencing that list, all three show up as same - [3, 0, 0, 0]. Hope this helps.

Sidmeister
  • 856
  • 2
  • 14
  • 27