jkortner
jkortner

Reputation: 631

How to Change a Value in a Dict in another Dict?

I created a dict of dicts in python.

dict1 = {}
dict2 = {'a': 0,
         'b': 0,
         'c': 0}
for i in range(1, 4):
    dict1.update({i : dict2})
print(dict1)
output: {1: {'a': 0, 'c': 0, 'b': 0}, 
         2: {'a': 0, 'c': 0, 'b': 0}, 
         3: {'a': 0, 'c': 0, 'b': 0}}

I now want to change the value of 'a' in the first dictionary.

dict1[1]['a'] += 1

The output looks like this.

print(dict1)
output: {1: {'a': 1, 'c': 0, 'b': 0}, 
         2: {'a': 1, 'c': 0, 'b': 0}, 
         3: {'a': 1, 'c': 0, 'b': 0}}

All 'a' values changed and not just the one in the first dictionary. Why is that? And how do I change only the value in the first dict?

Upvotes: 0

Views: 864

Answers (3)

Jay
Jay

Reputation: 24895

In your code, you are updating the reference of the same dictionary in all the places. Since, all those references point to the same object, when you modify one, it is reflected everywhere.

You need a deep copy and not a shallow copy i.e. not the reference of the same dictionary in all the places.

Try the below code:

import copy

dict1 = {}
dict2 = {'a': 0,
         'b': 0,
         'c': 0}
for i in range(1, 4):
    dict1.update({i : copy.deepcopy(dict2)})

EDIT:

As correctly pointed out by @Netwave and @gireesh4manu, I am adding an update here.

For the example in this particular question, a copy.deepcopy is not needed as contents are dictionary are all immutable. In this case, the below answer would suffice.

dict1 = {}
dict2 = {'a': 0,
         'b': 0,
         'c': 0}
for i in range(1, 4):
    dict1.update({i : dict2.copy()})

But, in case if dict2 were to contain some mutable objects, then copy.deepcopy will be needed. One such example of dict2 is below:

dict2: {'a': [1,2,3],
        'b': [4,5,6],
        'c':[]
       }

In this case, since dict2 contains lists, any changes to those lists will reflected everywhere as they are linked by reference. To avoid this, copy.deepcopy will be needed.

Upvotes: 3

olinox14
olinox14

Reputation: 6643

Dictionnaries are mutable objects, which means all of the values of dict2 are pointing to the same object in memory.

One way to force the instanciation of a new dict object at each iteration is using the dict() function:

for i in range(1, 4):
    dict1.update({i : dict(dict2)})

Upvotes: 1

Netwave
Netwave

Reputation: 42678

You are referencing the same dict (dict2) in all the new dict entries. Just copy the dict2 when updating the values in dict1:

>>> dict1 = {}
>>> dict2 = {'a': 0,
...          'b': 0,
...          'c': 0}
>>> dict1.update({i:dict2.copy() for i in range(1,4)})
>>> dict1
{1: {'a': 0, 'b': 0, 'c': 0}, 2: {'a': 0, 'b': 0, 'c': 0}, 3: {'a': 0, 'b': 0, 'c': 0}}
>>> dict1[1]["a"] = 1
>>> dict1
{1: {'a': 1, 'b': 0, 'c': 0}, 2: {'a': 0, 'b': 0, 'c': 0}, 3: {'a': 0, 'b': 0, 'c': 0}}

Upvotes: 3

Related Questions