Search⌘ K
AI Features

Shallow Copy vs Deep Copy

Explore how shallow and deep copies work in Python for built-in and custom objects. Understand when to use each copying method to maintain object independence and avoid unintended modifications. This lesson clarifies the concepts using practical examples involving lists and custom classes.

In this section, we’ll learn how to copy the objects in Python. You must have heard the terms shallow copy and deep copy before.

Alert: Just a heads up that for primitive types (int), there’s no difference between a shallow copy and a deep copy.

Python’s built-in mutable objects can be copied by using their constructor. For example:

l2 = list(l1)  # List l1 copied with list()
d2 = dict(d1)  # Dictionary d2 copied with dict()
s2 = set(s1)   # Set s2 copied with set()

Shallow copy

Creating an object and populating it with the references to the objects present in the original is called a shallow copy. Copying using the constructor or a factory function like we did in the above example, is creating a shallow copy. It’s just one level deep.

Let’s run an example and check whether the copied object is independent or not.

svg viewer
Python 3.10.4
l1 = [[1, 'a'], [2, 'b'], [3, 'c']]
l2 = l1[:] # Shallow copying l1 to l2
print(l2 is l1)

So, you can see we copied l1 into l2 at line 2, but they both are different as l2 is l1 evaluates to False.

⚙️ Note: The [:] operator is a shortcut to create a copy of a mutable sequence.

Look at the following snippet:

l1 = [[1, 'a'], [2, 'b'], [3, 'c']]
l2 = list(l1)

l1.append([4, 'd'])

Now, l1 equals [[1, 'a'], [2, 'b'], [3, 'c'], [4, 'd']] but l2 remains the same ([[1, 'a'], [2, 'b'], [3, 'c']]). This is because l2 still holds the references of the child objects from the original list stored in l1.

Now, what if we try to modify those child objects? Let’s try one and see what happens.

Python 3.10.4
l1 = [[1, 'a'], [2, 'b'], [3, 'c']]
l2 = list(l1)
l1[0][0] = 4
print(l2)

Modifying l1 also changes l2 because both share the same child objects.

So, wouldn’t it be better to create a deep copy in the first place to have independent objects from the very beginning?

Deep copy

Creating an object and populating it with the copies of the objects present in the original is called a deep copy.

Python provides a copy module with a deepcopy() function that creates a deep copy of an object passed to it as a parameter.

Run the following program.

svg viewer
Python 3.10.4
import copy
l1 = [[1, 'a'], [2, 'b'], [3, 'c']]
l2 = copy.deepcopy(l1) # Deep copying l1 to l2
l1[0][0] = 4
print(l2)

This time, l2 didn’t change, because l1 was cloned (copied) recursively, including all of its child objects.

⚙️ Note: The copy module also provides a copy() function to create shallow copies of objects.

What if we want to clone an arbitrary object, e.g., an object of a custom class? Let’s see how to do it.

Copying arbitrary objects

The copy module saves the day again by enabling us to clone the arbitrary objects. Let’s demonstrate it via an executable.

Python 3.10.4
import copy
# Creating a custom class
class Person:
def __init__(self, parents, siblings):
self.parents = parents
self.siblings = siblings
# Creating objects of Person class
person1 = Person(['Kim', 'Marry'], ['Joey', 'Katherine', 'Chris'])
person2 = copy.copy(person1) # Shallow copy
person3 = copy.deepcopy(person1) # Deep copy
# Verifying shallow copy
print(person2 is person1)
person1.siblings.append('Tim')
print(person2.siblings)
# Verifying deep copy
print(person3 is person1)
print(person3.siblings)

In the code above, we make a custom class Person. Then, at line 10, we create an object person1 using its constructor. Then using the copy module, we create a shallow and a deep copy of person1: person2 and person3 respectively.

We also test the behavior of the objects. The statement person2 is person1 returns False, which is the expected behavior from a shallow copy. Similarly, person3 is person1 returns False.

Look at line 16. We modify the siblings of person1, and this change was reflected in person2 being a shallow copy. But, person3 remains as it is because the child objects were recursively copied from person1.