Python problem – Editing value in dictionary inside two dimensional list edits the whole matrix instead of only one item

Question:

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
Asked By: Totallama

||

Answers:

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]
Answered By: Lorenz Hetterich

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
Answered By: Siew
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.