The key difference between your two snippets is that content['a']['v'] = 3
is a completely different operation than content['a'] = 3
. In the first case, you're modifying the inner dictionary by changing its v
key. In the latter case, you're replacing the value in the dictionary without modifying it.
It's confusing when everything's a dictionary, so let's replace the dictionaries with variables and instances of a class:
class Person:
def __init__(self, name):
self.name = name
# these two variables are represent your `content` dict
a = Person('Andy') # this variable represents `{'v': 1}`
b = Person('Belle') # this variable represents `{'v': 2}`
# the equivalent of `d1['k1'].update(content)` is a simple assignment
k1_a = a
# and the equivalent of `content['a']['v'] = 3` is changing a's name
a.name = 'Aaron'
# because k1_a and a are the same Person instance, this is reflected in k1_a:
print(k1_a.name) # output: Aaron
The key points to note here are that
k1_a = a
doesn't make a copy of the Person; similar to how d1['k1'].update(content)
doesn't make a copy of the {'v': 1}
dict.
a.name = 'Aaron'
modifies the Person; similar to how content['a']['v'] = 3
modifies the inner dict.
The equivalent of your 2nd snippet looks like this:
a = 'Andy'
b = 'Belle'
k1_a = a
a = 'Aaron'
print(k1_a) # output: Andy
This time, no object is ever modified. All we're doing is overwriting the value of the a
variable, exactly how content['a'] = 3
overwrites the value of the a
key in your dict.
If you don't want the changes in the inner dicts to be reflected in other dicts, you have to copy them with copy.deepcopy
:
import copy
content = {'a': {'v': 1}, 'b': {'v': 2}}
d1 = {'k1': {}}
d2 = {'k2': {}}
d1['k1'].update(copy.deepcopy(content))
print(d1)
content['a']['v'] = 3
content['b']['v'] = 4
d2['k2'].update(copy.deepcopy(content))
print(d2)
print(d1)
# output:
# {'k1': {'a': {'v': 1}, 'b': {'v': 2}}}
# {'k2': {'a': {'v': 3}, 'b': {'v': 4}}}
# {'k1': {'a': {'v': 1}, 'b': {'v': 2}}}