Home > Mobile >  Append not working after merging a dictionnary into a other nested dictonnary
Append not working after merging a dictionnary into a other nested dictonnary

Time:10-25

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.

  • Related