While reading up the documentation for dict.copy(), it says that it makes a shallow copy of the dictionary. Same goes for the book I am following (Beazley's Python Reference), which says:
The m.copy() method makes a shallow copy of the items contained in a mapping object and places them in a new mapping object.
Consider this:
>>> original = dict(a=1, b=2) >>> new = original.copy() >>> new.update({'c': 3}) >>> original {'a': 1, 'b': 2} >>> new {'a': 1, 'c': 3, 'b': 2} So I assumed this would update the value of original (and add 'c': 3) also since I was doing a shallow copy. Like if you do it for a list:
>>> original = [1, 2, 3] >>> new = original >>> new.append(4) >>> new, original ([1, 2, 3, 4], [1, 2, 3, 4]) This works as expected.
Since both are shallow copies, why is that the dict.copy() doesn't work as I expect it to? Or my understanding of shallow vs deep copying is flawed?
By "shallow copying" it means the content of the dictionary is not copied by value, but just creating a new reference. In contrast, a deep copy will copy all contents by value.
In Python, a shallow copy is a “one-level-deep” copy. The copied object contains references to the child objects of the original object. A deep copy is completely independent of the original object. It constructs a new collection object by recursively populating it with copies of the child objects.
In case of deep copy, a copy of object is copied in other object. It means that any changes made to a copy of object do not reflect in the original object. In python, this is implemented using “deepcopy()” function.
By "shallow copying" it means the content of the dictionary is not copied by value, but just creating a new reference.
>>> a = {1: [1,2,3]} >>> b = a.copy() >>> a, b ({1: [1, 2, 3]}, {1: [1, 2, 3]}) >>> a[1].append(4) >>> a, b ({1: [1, 2, 3, 4]}, {1: [1, 2, 3, 4]}) In contrast, a deep copy will copy all contents by value.
>>> import copy >>> c = copy.deepcopy(a) >>> a, c ({1: [1, 2, 3, 4]}, {1: [1, 2, 3, 4]}) >>> a[1].append(5) >>> a, c ({1: [1, 2, 3, 4, 5]}, {1: [1, 2, 3, 4]}) So:
b = a: Reference assignment, Make a and b points to the same object.
![Illustration of 'a = b': 'a' and 'b' both point to '{1: L}', 'L' points to '[1, 2, 3]'.](https://i.stack.imgur.com/4AQC6.png)
b = a.copy(): Shallow copying, a and b will become two isolated objects, but their contents still share the same reference
![Illustration of 'b = a.copy()': 'a' points to '{1: L}', 'b' points to '{1: M}', 'L' and 'M' both point to '[1, 2, 3]'.](https://i.stack.imgur.com/Vtk4m.png)
b = copy.deepcopy(a): Deep copying, a and b's structure and content become completely isolated.
![Illustration of 'b = copy.deepcopy(a)': 'a' points to '{1: L}', 'L' points to '[1, 2, 3]'; 'b' points to '{1: M}', 'M' points to a different instance of '[1, 2, 3]'.](https://i.stack.imgur.com/BO4qO.png)
Take this example:
original = dict(a=1, b=2, c=dict(d=4, e=5)) new = original.copy() Now let's change a value in the 'shallow' (first) level:
new['a'] = 10 # new = {'a': 10, 'b': 2, 'c': {'d': 4, 'e': 5}} # original = {'a': 1, 'b': 2, 'c': {'d': 4, 'e': 5}} # no change in original, since ['a'] is an immutable integer Now let's change a value one level deeper:
new['c']['d'] = 40 # new = {'a': 10, 'b': 2, 'c': {'d': 40, 'e': 5}} # original = {'a': 1, 'b': 2, 'c': {'d': 40, 'e': 5}} # new['c'] points to the same original['d'] mutable dictionary, so it will be changed
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