I have a matrix (two-dimensional list) filled with dictionary-type variable in the entire scope containing "val": False
The problem is when I want to change only one item in the matrix and chanhge the value to True for this one paticular item.
Somehow this part of code: matrix[3][2]["val"] = True
causes the entire matrix to update the "val" value and changes all False values to True.
Here is my code:
defval = {
"val": False
}
matrix = []
for x in range(5):
row = []
for i in range(5):
row.append(defval)
matrix.append(row)
matrix[3][2]["val"] = True
CodePudding user response:
This behavior arises due to variables in python being passed by reference rather than by value. For example:
some_dict = {'foo': 'bar'}
other_dict = some_dict # actually references the same object as some_dict
other_dict['foo'] = 'buzz' # update applies to the dictionary object being referenced
print(other_dict) # {'foo': 'buzz'}
print(some_dict) # {'foo': 'buzz'}
Therefore all elements in your matrix actually reference the same dictionary object, and when it is updated, the change is reflected in all references. To avoid this, you can use dictionary's copy method, which returns a shallow copy of a dictionary. So, your code could look something like this:
defval = {
"val": False
}
matrix = []
for x in range(5):
row = []
for i in range(5):
row.append(defval.copy())
matrix.append(row)
matrix[3][2]["val"] = True
CodePudding user response:
When using row.append(defval)
, python will not copy the dict stored in defval
, but will store a reference to the dict in the array.
Thus, all rows implicitly use the same array. When you modify the entry, all rows are modified since they all reference the same dict.
A similar example is given in the following code:
blah = [1]
some_list = [blah, blah]
some_list[0][0] = 2
print(some_list)
# [[2], [2]]
print(blah)
# [2]
blah_1 = [1]
blah_2 = [1]
some_list_2 = [blah_1 , blah_2]
some_list_2[0][0] = 2
print(some_list_2)
# [[2], [1]]
print(blah_1)
# [2]
print(blah_2)
# [1]