In Python, copying an object can be done in two ways: shallow copy and deep copy. Understanding the difference between these two is crucial because it determines how changes to the copied object affect the original object, especially when dealing with complex data structures like nested lists or dictionaries.
1. Shallow Copy:
A shallow copy creates a new object but does not recursively copy the objects contained within the original object. Instead, it copies references to the nested objects. So, changes made to the original or shallow-copied nested objects are reflected in both. However, changes to the outermost object are independent.
import copy
# Original list with nested structure
original = [[1, 2, 3], [4, 5, 6]]
# Shallow copy of the original
shallow_copied = copy.copy(original)
# Modify the outer list
shallow_copied.append([7, 8, 9])
print("Original after modifying shallow copy (outer list):", original)
print("Shallow copy:", shallow_copied)
# Modify an inner list (nested object)
shallow_copied[0][0] = 99
print("\nOriginal after modifying inner list:", original)
print("Shallow copy after modifying inner list:", shallow_copied)
Original after modifying shallow copy (outer list): [[1, 2, 3], [4, 5, 6]]
Shallow copy: [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
Original after modifying inner list: [[99, 2, 3], [4, 5, 6]]
Shallow copy after modifying inner list: [[99, 2, 3], [4, 5, 6], [7, 8, 9]]
As seen in the output:
However, when modifying an element in one of the nested lists, both the original and shallow-copied lists were affected. This is because the shallow copy only copies the reference to the inner lists, not their values. When we added a new list to the shallow copy, it didn’t affect the original list.
2. Deep Copy:
A deep copy creates a completely independent copy of the original object and all the objects nested within it. Changes to the deep-copied object do not affect the original object at all, and vice versa. The deepcopy
method recursively copies everything.
# Deep copy of the original
deep_copied = copy.deepcopy(original)
# Modify the inner list
deep_copied[0][0] = 42
print("\nOriginal after deep copy modification:", original)
print("Deep copy after modification:", deep_copied)
Original after deep copy modification: [[99, 2, 3], [4, 5, 6]]
Deep copy after modification: [[42, 2, 3], [4, 5, 6]]
Here, changing the inner list in the deep copy didn’t affect the original list, as expected. This is because deepcopy
recursively creates copies of all the objects inside the original.
Key Differences:
- Shallow Copy: Only copies references to nested objects (inner lists, dictionaries, etc.), so changes to these nested objects will affect both the original and shallow copy.
- Deep Copy: Recursively copies everything, so changes to the deep copy or the original object have no effect on each other.
Use Cases:
- Shallow Copy is useful when the object structure is flat (no nested objects) or when you want to share references to the nested objects between the original and copied objects.
- Deep Copy is useful when you need a completely independent copy of the entire object, including all nested objects, ensuring that changes in one copy do not affect the other.