Python Shallow Copy and Deep Copy
In Python, you can copy an object using either a Shallow Copy or a Deep Copy, depending on whether you want the copy to be independent of the original or not.
The Wrong Way to Copy an Object in Python
In Python, the =
operator does not create a true copy of an object. Instead, it creates a new reference to the existing object!
To better understand this problem, consider this example in which a list named old_list
is created and an object reference is passed to new_list
using =
operator:
old_list = [[1, 2, 3], [4, 5, 6], [7, 8, 'a']]
new_list = old_list
new_list[2][2] = 9
print('Old List:', old_list)
print('ID of Old List:', id(old_list))
print('New List:', new_list)
print('ID of New List:', id(new_list))
and the output is:
Old List: [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
ID of Old List: 132938583248128
New List: [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
ID of New List: 132938583248128
Notice that both variables old_list
and new_list
share the same ID (140673303268168
), indicating that they both point to the same object in memory. This means that changes made to old_list
and new_list
are actually being made to the same object.
Types of Copy in Python
In Python, there are two ways to create copies:
- Shallow Copy
- Deep Copy
To make these copy work, we use the copy
module: it allows to do shallow and deep copy operations.
import copy
copy.copy(x) # returns shallow copy of x
copy.deepcopy(x) # returns deep copy of x
Shallow Copy
A Shallow Copy is a copy of an object that does not create a new instance of the object's nested objects, but references the same nested objects in the original.
This means that if you modify a nested object in the surface copy, the corresponding nested object in the original object will also be modified, because both the original and the copy refer to the same nested object.
For example, create a nested list, shallow copy it using copy()
method and then do some changes:
import copy
old_list = [1, 2, [3, 5], 4]
new_list = copy.copy(old_list)
# Modifying the nested list in the shallow copy
new_list[2][0] = 7
# Original list is affected because the nested list is the same instance
print(old_list) # Output: [1, 2, [7, 5], 4]
print(new_list) # Output: [1, 2, [7, 5], 4]
When you change any nested elements within old_list
, these changes are also reflected in new_list
. This happens because both lists are referencing the same memory locations for those nested elements. Essentially, you're updating the values in memory via a pointer mechanism.
However, if you add a new sublist to old_list
, this addition is exclusive to old_list
. It will not be seen in new_list
because new_list maintains references to the original nested objects, and you're only appending a new value, not a reference to another object.
import copy
old_list = [[1, 1, 1], [2, 2, 2], [3, 3, 3]]
new_list = copy.copy(old_list)
old_list.append([4, 4, 4])
print(old_list) # [[1, 1, 1], [2, 2, 2], [3, 3, 3], [4, 4, 4]]
print(new_list) # [[1, 1, 1], [2, 2, 2], [3, 3, 3]]
Deep Copy
A Deep Copy consists of creating a new object and recursively inserting copies of the items found in the original object into it.
This process ensures that the new object is completely independent of the original one: any changes made to the deep copy will not affect the original object and vice versa.
For example, create a nested list, deep copy it using deepcopy()
method and then do some changes:
import copy
old_list = [[1, 1, 1], [2, 2, 2], [3, 3, 3]]
new_list = copy.deepcopy(old_list)
# Modifying the nested list in the deep copy
new_list[2][0] = 0
new_list[2][1] = 0
new_list[2][2] = 0
print(old_list) # [[1, 1, 1], [2, 2, 2], [3, 3, 3]]
print(new_list) # [[1, 1, 1], [2, 2, 2], [0, 0, 0]]
If you make changes to any nested objects in original object old_list
, you will see no changes to the copy new_list
.
Summary of the differences between Shallow Copy and Deep Copy
The main differences between a shallow copy and a deep copy in Python are:
-
Shallow Copy
- Quickly duplicates the outer structure of the original object, but the inner objects are not copied; references to the original objects are kept instead.
- Changes to the copied object's inner objects will affect the original object's inner objects, as they are pointing to the same memory location.
- Generally faster than a deep copy because it does not need to duplicate the nested objects.
-
Shallow Copy:
- Quickly duplicates the outer structure of the original object, but the inner objects are not copied; references to the original objects are kept instead.
- Changes to the copied object's inner objects will affect the original object's inner objects, as they are pointing to the same memory location.
- Generally faster than a deep copy because it does not need to duplicate the nested objects