input
first_dict = {"block_1": {"col_A": [], "col_B": []},
"block_2": {"col_D": [], "col_E": []}}
second_dict = {"col_Z": []}
initial manipulations
I added the second_dict
to all blocks of first_dict
(2nd level)
# achieved with
for block in first_dict.keys():
first_dict[block] = {**first_dict[block], **second_dict}
# I get what I expected
{'block_1': {'col_A': [], 'col_B': [], 'col_Z': []},
'block_2': {'col_D': [], 'col_E': [], 'col_Z': []}}
issue
Now when I try to append a new value in block_2/col_Z, the value is also added to block_1/col_Z
# following
first_dict["block_2"]["col_Z"].append("bar")
# produce
{'block_1': {'col_A': [], 'col_B': [], 'col_Z': ['bar']},
'block_2': {'col_D': [], 'col_E': [], 'col_Z': ['bar']}}
# instead of
{'block_1': {'col_A': [], 'col_B': [], 'col_Z': []},
'block_2': {'col_D': [], 'col_E': [], 'col_Z': ['bar']}}
my current investigation
I'm suspecting my initial manipulations to inserted dict which all pointing to the same memory address, but I can't figure how to fix it.
hex(id(first_dict["block_1"]["col_Z"]))
==> '0x7f72687b9b80'
hex(id(first_dict["block_2"]["col_Z"]))
==> '0x7f72687b9b80'
CodePudding user response:
As you suspected, the issue you're having is related to Python not implicitly making copies of your dictionary when you assign it. Usually one would use dict.copy()
or some other way of shallow copying the dictionary itself, however that wouldn't really work in this case.
This is because shallow copying only copies the first object, namely the dictionary in this case, and reuses all other objects. In this case you have a list inside of your dictionary, so using copy wouldn't be enough as you would use a new dictionary but your lists would still be the same object as the original.
In this case you have to use deepcopy
from copy
.
import deepcopy from copy
for block in first_dict.keys():
first_dict[block] = {**first_dict[block], **deepcopy(second_dict)}
Where deepcopy
copies all objects found inside of the original object, where the original object is the dictionary in this case.
Also, while there is nothing wrong with doing it this way, using update is cleaner.
import deepcopy from copy
for block in first_dict.keys():
first_dict[block].update(deepcopy(second_dict))
CodePudding user response:
According to this article you can use dict_name.copy()
or dict(dict_name)
to copy the dictionary instead of copying the reference.