I don't understand these cases:
content = {'a': {'v': 1}, 'b': {'v': 2}}
d1 = {'k1': {}}
d2 = {'k2': {}}
d1['k1'].update(content)
print(d1)
content['a']['v'] = 3
content['b']['v'] = 4
d2['k2'].update(content)
print(d2)
print(d1)
>>> {'k1': {'a': {'v': 1}, 'b': {'v': 2}}}
>>> {'k2': {'a': {'v': 3}, 'b': {'v': 4}}}
>>> {'k1': {'a': {'v': 3}, 'b': {'v': 4}}}
In the case above the content of d1 is changed after the variable content is updated.
content = {'a': 1, 'b': 2}
d1 = {'k1': {}}
d2 = {'k2': {}}
d1['k1'].update(content)
print(d1)
content['a'] = 3
content['b'] = 4
d2['k2'].update(content)
print(d2)
print(d1)
>>> {'k1': {'a': 1, 'b': 2}}
>>> {'k2': {'a': 3, 'b': 4}}
>>> {'k1': {'a': 1, 'b': 2}}
However in this case d1 is not altered even if the variable content was changed. I don't understand why... any idea?
Use copy() This is a built-in Python function that can be used to create a shallow copy of a dictionary. This function takes no arguments and returns a shallow copy of the dictionary. When a change is made to the shallow copy, the original dictionary will remain unchanged.
The dict. copy() method returns a shallow copy of the dictionary. The dictionary can also be copied using the = operator, which points to the same object as the original. So if any change is made in the copied dictionary will also reflect in the original dictionary.
Copy a dictionary with a for loop To copy a dictionary it is also possible to use a for loop: >>> d1 = {'a':1,'b':2} >>> d2 = {} >>> for key in d1: ... d2[key] = d1[key] ...
see shallow vs deep copy.
The copy here is a shallow copy so the first level entries are copies but the nested structures are references.
- A shallow copy constructs a new compound object and then (to the extent possible) inserts references into it to the objects found in the original.
- A deep copy constructs a new compound object and then, recursively, inserts copies into it of the objects found in the
original.
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}}}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With