Reputation: 631
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
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
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
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