0

I am trying to create a list of size n with each element also being a list of size m. After the creation of the list, I perform the following operation.

matrix=[[0]*m]*n 
# matrix = [[0 for i in range(0,m)] for j in range(0,n)]
m=2
n=3
ind=[[0,1][1,1]]
for r,c in ind:
   for i in range(m):
      matrix[r][i]+=1
   for j in range(n):
      matrix[j][c]+=1
print(matrix)

The above operation looks for the row and column value in the list "ind" and increments the value by one of the corresponding row and column.

The problem is when I am using the matrix initialization as [[0]*m]*n then the result is coming different and when I am using matrix = [[0 for i in range(0,m)] for j in range(0,n)] the result is coming correct. In the first case the values get changed for all the rows, columns which shouldn't be the case.

I tried doing the type of the individual elements of the matrix list as well as getting the type of the element of the matrix element using print(type(matrix[0])) and print(type(matrix[0][0]))

Both have the same type. Any idea why the result of the matrix is coming different for the 2 different type of initialization?

Thanks for the help.

wjandrea
  • 23,210
  • 7
  • 49
  • 68
user7319461
  • 19
  • 1
  • 6

1 Answers1

-1

When you do:

[0]*m

you are creating a list, which we'll call l1. So the next step:

[[0]*m]*n 

Is equivalent to:

[l1]*n

This does not copy l1 mutliple times, but rather makes multiple references to it. The classic deep-copy vs shallow-copy issue.

You can confirm it by checking that the following expression is True

matrix[0] is matrix[1]

Using a list comprehension each row is a different list, so you don't have that problem

matrix=[[0]*m for _ in range(n)] 

You may wonder why this referencing is a problem for the lists, but you can do [0]*m without worrying that all of the 0's are actually referencing the same value.

The difference here is the type, lists will be copied-by-reference by default since long lists can be expensive to copy-by-value. ints are pretty cheap to copy, so it doesn't make as much sense to create references

imochoa
  • 675
  • 4
  • 8
  • 3
    The explanation at the end is plain wrong. It has nothing to do with anything like copy by reference. The only reason why you don't get into problems in this case is that you can't mutate an int, so the only thing you can do to an int that is an item of a list is replace it by another object. Problems occur when the list items are lists and you mutate (not replace) some of these lists. – Thierry Lathuille Jun 04 '22 at 17:03