Why does python replace every object of a column, when only referring to one, if all lines are identical?
Question:
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.
Answers:
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
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.
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