0

When trying to change one value in a matrix, python will change all items of that column with the desired value, despite the fact I am only trying to change one. But this only happens when all rows are identical.

Example:

def print_matrix(matrix: list[list], dlm: str) -> None:

    for row in matrix:

        for col in row:

            print(col, end = dlm)

        print()

        

one_row = list(range(4))

test_matrix = []

for i in range(5):

    test_matrix.append(one_row)

test_matrix[0][0] = 5

sec_matrix =[

    [0,1,2,3],

    [0,1,2,3],

    [0,1,2,3],

    [0,1,2,4]

]

sec_matrix[0][0]=5

print_matrix(test_matrix, ' ')

print()

print_matrix(sec_matrix, ' ')

In the first matrix every 0 gets replaced with a 5, despite only referencing the first item of the first list. In the second one it works the way I want it to, because the last list is slightly different. Why is there a difference in the way test_matrix and sec_matrix are treated? Is this a bug, or intended? Does python just think they are the same list because they look the same? Or are they even the same to increase performance? Either way I don't think it should happen.

I tried to update a matrix item on certain coordinates. I expected only the desired item to be altered, instead every single one of that column got changed. Problem is fixed by not having identical rows.

rmm2908
  • 3
  • 2
  • 1
    Because your list has *5 references to the same list* inside of it. What did you think would happen when you did `for i in range(5): test_matrix.append(one_row)`? – juanpa.arrivillaga Nov 28 '22 at 01:14
  • 2
    "Is this a bug, or intended? Does python just think they are the same list because they look the same? " *No*. They are the same list **because you put the same list in there multiple times**. On the other hand, with `sec_list`, you create a list with 5 different references to *different lists* that were created as a part of your list literal. Python is not guessing or making performance optimizations, it is behaving *exactly* as documented – juanpa.arrivillaga Nov 28 '22 at 01:15
  • Thank you. Looks like I just didn't understand lists correctly. I thought it would be the same appending the list as typing it out. I thought they became completely separate entities once they were appended to the matrix. – rmm2908 Nov 28 '22 at 01:25

1 Answers1

0

The reason is when you write test_matrix.append(one_row) you are appending actually [0,1,2,3] 5 times to test_matrix, essentially, i.e the list will look like [[0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3]]. Here each list element is a list with [0,1,2,3] references to the same [0,1,2,3]. When you then modify this single [0,1,2,3] it is visible via all references to it. For debugging purposes, you can check it,

print(id(test_matrix[0]))
print(id(test_matrix[1]))

So you will see all are the same id, if you want to do it then you can do it like below- where test_matrix = [ list(range(4)) for n in range(5) ] will re-generate value each time

def print_matrix(matrix, dlm):
    for row in matrix:
        for col in row:
            print(col, end = dlm)
        print()

    
test_matrix = []
test_matrix = [ list(range(4)) for n in range(5) ] # re-generate and appending

test_matrix[0][0] = 7
sec_matrix =[
    [0,1,2,3],
    [0,1,2,3],
    [0,1,2,3],
    [0,1,2,4]
]

sec_matrix[0][0]=5
print_matrix(test_matrix, ' ')
print()
print_matrix(sec_matrix, ' ')

Output:

7 1 2 3 
0 1 2 3 
0 1 2 3 
0 1 2 3 
0 1 2 3 

5 1 2 3 
0 1 2 3 
0 1 2 3 
0 1 2 4 
A l w a y s S u n n y
  • 36,497
  • 8
  • 60
  • 103
  • In [How to Answer](https://stackoverflow.com/help/how-to-answer), note the section _Answer Well-Asked Questions_, and the bullet point therein regarding questions that "have been asked and answered many times before". – Charles Duffy Nov 28 '22 at 01:33
  • @CharlesDuffy noted sir, will keep it in mind. Actually, I was not aware that it is already asked many times. – A l w a y s S u n n y Nov 28 '22 at 01:37