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.
- Shallow Copy
- 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'}]
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