Shallow Copy and Deep Copy
In this article, we will learn about shallow copy and deep copy in Python.
In Python, we use the assignment (=
) operator to create a copy of an object. However, it doesn’t make a new object. Instead, it just shares the reference of the original object to a new variable.
In the following example, the old_list
hold value [1, 2, 3]
and assing to new variable named new_list
by using assignment(=
) operator. If we modify the new_list
, the old_list
will also be affected. You can also see that the old_list
and new_list
id are the same, i.e., 4350750272
.
>>> old_list = [1, 2, 3]
>>> new_list = old_list
>>> new_list[2] = 0
>>> print(old_list)
[1, 2, 0]
>>> print(new_list)
[1, 2, 0]
>>> print(f"id of new_list {id(new_list)}, id of old_list {id(old_list)}")
id of new_list 4350750272, id of old_list 4350750272
Why do we need a deep copy or a shallow copy?
Sometimes we need to keep original values unchanged and only modified in the new ones or vice versa. In Python, we have two ways to do this.
- Shallow copy
- Deep copy
Python copy Module
Python has a copy
module for the deep and shallow copy.
copy.copy(x) Return a shallow copy of x.
copy.deepcopy(x) Return a deep copy of x.
exception copy.Error Raised for module-specific errors.
Shallow Copy
A shallow copy creates new objects that store the original objects’ reference. A shallow copy doesn’t create a copy of nested objects where, as it only copies the reference of the nested objects. [1]
Create a copy using shallow copy
>>> import copy
>>> old_list = [[1, 2], [3, 4]]
>>> new_list = copy.copy(old_list)
>>> print(old_list)
[[1, 2], [3, 4]]
>>> print(new_list)
[[1, 2], [3, 4]]
In the above example, we create a nested list and shallow copy the value to another variable named new_list
using the copy
method, it will create independent objects with the same content.
Now we add some data in old_list
.
>>> old_list.append([5,6])
>>> print(old_list)
[[1, 2], [3, 4], [5, 6]]
>>> print(new_list)
[[1, 2], [3, 4]]
Here, we append new list [5, 6]
to old_list
. The new_list
contains references of original nested objects stored in old_list
. The new sublist [5, 6]
was not copied in new_list
. But, if you change any nested objects in the old_list
, the changes also reflect in the new_list
because both lists share the reference of the same nested objects.
>>> old_list[1][1] = 'X'
>>> print(old_list)
[[1, 2], [3, 'X'], [5, 6]]
>>> print(new_list)
[[1, 2], [3, 'X']]
Deep Copy
A deep copy creates a new object and recursively adds the copies of nested objects present in the original elements. [1]
Create a copy using deep copy
>>> import copy
>>> old_list = [[1, 2], [3, 4]]
>>> new_list = copy.deepcopy(old_list)
>>> print(old_list)
[[1, 2], [3, 4]]
>>> print(new_list)
[[1, 2], [3, 4]]
If any changes to nested objects of the old_list
, the changes are not reflected in new_list
.
>>> import copy
>>> old_list = [[1, 2], [3, 4]]
>>> new_list = copy.deepcopy(old_list)
>>> old_list[1][1] = 'X'
>>> print(old_list)
[[1, 2], [3, 'X']]
>>> print(new_list)
[[1, 2], [3, 4]]
What is the Difference Between Deep and Shallow Copies? [2]
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.
References:
[1] https://www.programiz.com/python-programming/shallow-deep-copy