user225312 user225312 - 13 days ago 4
Python Question

Understanding dict.copy() - shallow or deep?

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?

Answer

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:

  1. a = b: Reference assignment, Make a and b points to the same object.

    a ---,
         v
         {1: L}
         ^   |
    b ---'   '----> [1,2,3]
    
  2. a = b.copy(): Shallow copying, a and b will become two isolated objects, but their contents still share the same reference

    a ---> {1: L}
               |             
               >---> [1,2,3]
               |
    b ---> {1: M}
    
  3. a = copy.deepcopy(b): Deep copying, a and b's structure and content become completely isolated.

    a ---> {1: L}
               ‘-----> [1,2,3]
    b ---> {1: M}
               ‘-----> [1,2,3]
    
Comments