deep copy vs shallow copy in python

deep copy vs shallow copy in python

copy in python is used to copy objects as new names. We can copy python objects in two ways.

  1. Shallow Copy
  2. Deep Copy

Before discussing the copy module lets talk a little bit about the assignment operator in python.

a = [1,2,3,4]
b = a
print("Memory ID of A `a` ", id(a))
print("Memory ID of A `b` ", id(b))

b[0] = 1000
print(a)
# [1000, 2, 3, 4]
print(b)
# [1000, 2, 3, 4]

Above code give the output like below

Memory ID of A `a`  140393069299080
Memory ID of A `b`  140393069299080

From the above example, we can see that python is not copying the contents when performing the assignment, instead it's referencing the actual object to the name. So, changing data of will reflect in both names.

Shallow copy in python

Unlike the assignment operator shallow copy copies the contents and creates the new object. Let's see a simple example

import copy

a = [1,2,3,4,5]
b = copy.copy(a)

print("Memory ID of A `a` ", id(a))
print("Memory ID of A `b` ", id(b))

b[0] = 1000
print(a)
# [1, 2, 3, 4]
print(b)
# [1000, 2, 3, 4]

In above when we print the ids it will give us the output like below

Memory ID of A `a`  140393062406280
Memory ID of A `b`  140393062406344

We can clearly see that both the ids of the names were different. Unlike the assignment operation, shallow copy creates a copy of the referenced object. Shallow copy fails to deal with the complex data like nested objects (list of lists, list of dicts, etc).

Deep copy in python

The difference between shallow and deep copying is only relevant for compound objects (objects that contain other objects, like lists or class instances):

  • 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.

Let's see an example for shallow copy

import copy

d = {1: "one", 2: "two"}
a = [1,2,3,4, d]
b = copy.copy(a)
# Now change the contents of d
a[0] = 1000
d[3] = "three"
print("Contents of `a`", a)
# Contents of `a` [1000, 2, 3, 4, {1: 'one', 2: 'two', 3: 'three'}]
print("Contents of `b`", b)
# Contents of `b` [1, 2, 3, 4, {1: 'one', 2: 'two', 3: 'three'}]
In the above example we have complex data i.e a dict inside the list. When we copy the list with shallow copy it copied the object but kept the reference of the dict instead copying its contents.

Let's see an example for deep copy

import copy

d = {1: "one", 2: "two"}
a = [1,2,3,4, d]
b = copy.deepcopy(a)
# Now change the contents of d
a[0] = 1000
d[3] = "three"
print("Contents of `a`", a)
# Contents of `a` [1000, 2, 3, 4, {1: 'one', 2: 'two', 3: 'three'}]
print("Contents of `b`", b)
# Contents of `b` [1, 2, 3, 4, {1: 'one', 2: 'two'}]

From the above example we can see that deepcopy completely copied the object and all it's members.

Reference: https://docs.python.org/3/library/copy.html