How to Copy Class Instances in Python: Shallow vs Deep Copy
Use copy.copy and copy.deepcopy to clone class instances, showing how nested objects are shared or duplicated.
Python code
22 linesimport copy
class Config:
def __init__(self):
self.settings = {"theme": "dark", "language": "en"}
if __name__ == "__main__":
original = Config()
shallow_copy = copy.copy(original)
deep_copy = copy.deepcopy(original)
shallow_copy.settings["theme"] = "light"
deep_copy.settings["theme"] = "blue"
print(f"Original theme: {original.settings['theme']}")
print(f"Shallow copy theme: {shallow_copy.settings['theme']}")
print(f"Deep copy theme: {deep_copy.settings['theme']}")
print(f"Original and shallow share dict: {original.settings is shallow_copy.settings}")
print(f"Original and deep share dict: {original.settings is deep_copy.settings}")
Output
Original theme: dark
Shallow copy theme: light
Deep copy theme: blue
Original and shallow share dict: True
Original and deep share dict: False
How it works
copy.copy creates a new instance but keeps references to the same nested objects, so the settings dict is shared between the original and the shallow copy. copy.deepcopy recursively duplicates all nested objects, giving the deep copy its own independent settings dict. That is why changing shallow_copy.settings['theme'] also changes original.settings, while deep_copy stays independent. This behavior matters whenever your class holds mutable attributes like lists, dicts, or other custom objects. Use copy.deepcopy when you need a fully independent clone, and copy.copy when you only need to duplicate the top-level object.
Common mistakes
- Using the assignment operator `b = a` thinking it creates a copy—it only creates a new reference to the same object.
- Forgetting that `copy.copy` is shallow and nested mutable attributes remain shared.
- Assuming `copy.deepcopy` can copy everything—objects with locks or file handles may raise errors.
Variations
- Implement a `__copy__` or `__deepcopy__` method on your class to customize copy behavior.
- Use `copy.replace(instance, **changes)` (Python 3.13+) or `dataclasses.replace` for immutable dataclasses.
Real-world use cases
- Cloning a configuration object before applying temporary overrides without mutating the global settings.
- Duplicating a game state object for undo/redo operations where each snapshot must be fully independent.
- Creating a backup of a data model object before batch updates, ensuring rollback logic works correctly.
Sponsored
More from OOP & classes
- Add property getter setter validation in Python easy
- Binary Tree Inorder Traversal in Python easy
- Borg pattern shared state in Python medium
- Bridge Pattern in Python: Separate Abstraction from Implementation medium
- Composable Predicates with the &, |, ~ Operators in Python medium
- Composition over Inheritance: How to Build a Wallet Account in Python easy
Keep learning
Related tutorials and quizzes for this topic.