Understanding Shallow Copy and Deep Copy in Python with Examples
This article explains the concepts of shallow copy and deep copy in Python, describes their differences, and provides numerous code examples—including lists, dictionaries, and custom classes—to demonstrate how to use the copy module’s copy and deepcopy functions effectively.
When you need to duplicate an object, copying its reference is often insufficient; you must create an independent copy. This is where shallow copy and deep copy become essential.
Shallow Copy creates a new object and fills it with references to the original object's elements; immutable types are effectively duplicated, while mutable types retain references.
Deep Copy creates a new object and recursively copies all objects found within the original, producing a fully independent clone.
Example Code
First, import the copy module, which provides the copy and deepcopy functions.
1. Shallow copy of a list
import copy
original_list = [1, 2, [3, 4]]
shallow_copied_list = copy.copy(original_list)
original_list.append(5)
original_list[2].append(6)
print("Original List:", original_list) # Output: [1, 2, [3, 4, 6], 5]
print("Shallow Copied List:", shallow_copied_list) # Output: [1, 2, [3, 4, 6]]2. Deep copy of a list
import copy
original_list = [1, 2, [3, 4]]
deep_copied_list = copy.deepcopy(original_list)
original_list.append(5)
original_list[2].append(6)
print("Original List:", original_list) # Output: [1, 2, [3, 4, 6], 5]
print("Deep Copied List:", deep_copied_list) # Output: [1, 2, [3, 4]]3. Shallow copy of a dictionary
import copy
original_dict = {'a': 1, 'b': 2, 'c': [3, 4]}
shallow_copied_dict = copy.copy(original_dict)
original_dict['c'].append(5)
print("Original Dict:", original_dict) # Output: {'a': 1, 'b': 2, 'c': [3, 4, 5]}
print("Shallow Copied Dict:", shallow_copied_dict) # Output: {'a': 1, 'b': 2, 'c': [3, 4, 5]}4. Deep copy of a dictionary
import copy
original_dict = {'a': 1, 'b': 2, 'c': [3, 4]}
deep_copied_dict = copy.deepcopy(original_dict)
original_dict['c'].append(5)
print("Original Dict:", original_dict) # Output: {'a': 1, 'b': 2, 'c': [3, 4, 5]}
print("Deep Copied Dict:", deep_copied_dict) # Output: {'a': 1, 'b': 2, 'c': [3, 4]}5. Shallow copy of a custom class
import copy
class MyClass:
def __init__(self, value):
self.value = value
original_obj = MyClass([1, 2, 3])
shallow_copied_obj = copy.copy(original_obj)
original_obj.value.append(4)
print("Original Value:", original_obj.value) # Output: [1, 2, 3, 4]
print("Shallow Copied Value:", shallow_copied_obj.value) # Output: [1, 2, 3, 4]6. Deep copy of a custom class
import copy
class MyClass:
def __init__(self, value):
self.value = value
original_obj = MyClass([1, 2, 3])
deep_copied_obj = copy.deepcopy(original_obj)
original_obj.value.append(4)
print("Original Value:", original_obj.value) # Output: [1, 2, 3, 4]
print("Deep Copied Value:", deep_copied_obj.value) # Output: [1, 2, 3]7. Defining a custom __copy__ method
import copy
class MyClass:
def __init__(self, value):
self.value = value
def __copy__(self):
return MyClass(self.value[:])
original_obj = MyClass([1, 2, 3])
shallow_copied_obj = copy.copy(original_obj)
original_obj.value.append(4)
print("Original Value:", original_obj.value) # Output: [1, 2, 3, 4]
print("Shallow Copied Value:", shallow_copied_obj.value) # Output: [1, 2, 3]8. Defining a custom __deepcopy__ method
import copy
class MyClass:
def __init__(self, value):
self.value = value
def __deepcopy__(self, memo):
return MyClass(copy.deepcopy(self.value, memo))
original_obj = MyClass([1, 2, 3])
deep_copied_obj = copy.deepcopy(original_obj)
original_obj.value.append(4)
print("Original Value:", original_obj.value) # Output: [1, 2, 3, 4]
print("Deep Copied Value:", deep_copied_obj.value) # Output: [1, 2, 3]9. Shallow copy of a complex structure
import copy
original_complex = [1, 2, [3, 4], {'a': 5, 'b': [6, 7]}]
shallow_copied_complex = copy.copy(original_complex)
original_complex[2].append(8)
original_complex[3]['b'].append(9)
print("Original Complex:", original_complex) # Output: [1, 2, [3, 4, 8], {'a': 5, 'b': [6, 7, 9]}]
print("Shallow Copied Complex:", shallow_copied_complex) # Output: [1, 2, [3, 4, 8], {'a': 5, 'b': [6, 7, 9]}]10. Deep copy of a complex structure
import copy
original_complex = [1, 2, [3, 4], {'a': 5, 'b': [6, 7]}]
deep_copied_complex = copy.deepcopy(original_complex)
original_complex[2].append(8)
original_complex[3]['b'].append(9)
print("Original Complex:", original_complex) # Output: [1, 2, [3, 4, 8], {'a': 5, 'b': [6, 7, 9]}]
print("Deep Copied Complex:", deep_copied_complex) # Output: [1, 2, [3, 4], {'a': 5, 'b': [6, 7]}]These examples demonstrate that a shallow copy only duplicates the top‑level structure, while a deep copy recursively clones all nested objects, ensuring complete independence between the original and the copy.
Test Development Learning Exchange
Test Development Learning Exchange
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.