Search code examples
pythondictionarypass-by-referencedeep-copy

python dictionary value update


I have the following variables :

list_m = ["a","b","c"]
list_s = ['x','y','z']
dict_m = dict.fromkeys(list_m[:])
dict_s = dict.fromkeys(list_s[:],copy.deepcopy(dict_m)) # empty dict of dicts 

So I have

In[22]: dict_s
Out[22]: 
{'x': {'a': None, 'b': None, 'c': None},
 'y': {'a': None, 'b': None, 'c': None},
 'z': {'a': None, 'b': None, 'c': None}}

On updating a value of dict_s like this

 dict_s['x']['a']= np.arange(10)

I get

In[27]: dict_s
Out[27]: 
{'x': {'a': array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]), 'b': None, 'c': None},
 'y': {'a': array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]), 'b': None, 'c': None},
 'z': {'a': array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]), 'b': None, 'c': None}}

instead of what i wanted/expected:

In[27]: dict_s
Out[27]: 
{'x': {'a': array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]), 'b': None, 'c': None},
 'y': {'a': None, 'b': None, 'c': None},
 'z': {'a': None, 'b': None, 'c': None}}

I don't exactly understand if this is a deep/shallow copy issue or something else.


Solution

  • fromkeys uses the same default value for each key. If you want separate values you can use dict comprehension and generate new dict for each value with fromkeys:

    >>> list_m = ["a","b","c"]
    >>> list_s = ['x','y','z']
    >>> dict_s = {x: dict.fromkeys(list_m) for x in list_s}
    >>> dict_s
    {'y': {'a': None, 'c': None, 'b': None}, 'x': {'a': None, 'c': None, 'b': None}, 'z': {'a': None, 'c': None, 'b': None}}
    >>> dict_s['y']['a'] = 100
    >>> dict_s
    {'y': {'a': 100, 'c': None, 'b': None}, 'x': {'a': None, 'c': None, 'b': None}, 'z': {'a': None, 'c': None, 'b': None}}