Shallow Copy and Deep Copy in Python
Shallow copy and deep copy are two concepts in Python about duplicating data structures like lists, dictionaries, or user-defined objects. They both create a new object but handle the copying of nested objects differently, such as lists inside lists.
1. Shallow Copy
A shallow copy creates a new object that is a copy of the original. However, it does not recursively copy objects that are contained within the original. Instead, it only copies references to those inner objects.
Key Characteristics
- A new object is declared.
- Inner (nested) objects are not copied, but only references to them are.
- The mutable inner objects are changed both for the original and the copied object.
How to Create a Shallow Copy
1. Using the copy module:
import copy
shallow_copy = copy.copy(original_object)
2. Using slicing (for lists):
shallow_copy = original_list[:]
3. Using the list() or dict() constructor:
shallow_copy = list(original_list)
shallow_copy = dict(original_dict)
Example
import copy
original_list = [[1, 2, 3], [4, 5, 6]]
shallow_copy = copy.copy(original_list)
# Modify the inner list
shallow_copy[0][0] = 99
print("Original List:", original_list)
print("Shallow Copy:", shallow_copy)
Output:
Original List: [[99, 2, 3], [4, 5, 6]]
Shallow Copy: [[99, 2, 3], [4, 5, 6]]
Explanation:
- The outer list is copied as a new object.
- The inner lists are still shared references between
original_listandshallow_copy. - Modifying the inner list affects both the original and the shallow copy.
2. Deep Copy
A deep copy produces a new object and recursively duplicates all objects within the original so that the result is a completely independent copy.
Key Characteristics
- A new object is created.
- Inner (nested) objects are copied as well.
- Inner objects in the copy do not have any effects on the original and vice versa.
How to Create a Deep Copy
Using the copy module:
import copy
deep_copy = copy.deepcopy(original_object)
Example
import copy
original_list = [[1, 2, 3], [4, 5, 6]]
deep_copy = copy.deepcopy(original_list)
# Modify the inner list
deep_copy[0][0] = 99
print("Original List:", original_list)
print("Deep Copy:", deep_copy)
Output:
Original List: [[1, 2, 3], [4, 5, 6]]
Deep Copy: [[99, 2, 3], [4, 5, 6]]
Explanation:
- Both the outer list and the inner lists are duplicated.
- Changes made to the
deep_copydo not affect theoriginal_list, as they are completely independent objects.
Comparison: Shallow Copy vs. Deep Copy
| Feature | Shallow Copy | Deep Copy |
|---|---|---|
| Definition | Copies the object without nested objects | Copies the object and all nested objects recursively |
| Nested Object | References are copied | Entire structure is duplicated |
| Memory Usage | Lower | Higher |
| Modification Effect | Affects both original and copy | Changes are independent |
When to Use Which?
- Shallow Copy: Use when the inner objects of the original object will not change, or when you intentionally want the original and copied objects to share the same inner objects.
- Deep Copy: Use when you need a completely independent copy and want to avoid any unintended side effects caused by shared references.
Important Points
1. Immutable Objects:
- For immutable objects (for example, integers, strings, tuples), both shallow copy and deep copy perform identically as the objects are not modifiable.
2. Performance:
- Shallow copy is faster with less memory requirements.
- Deep copy may be slower and more memory-intensive because of the recursive copy.
3. Cyclic References:
- The
deepcopymethod handles cyclic references (when an object has a reference back to itself). The method prevents an infinite recursion during its copy operation.