Deep copy of a dict in python
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
In Python, dictionaries are mutable data structures used extensively for storing key-value pairs. When you need a completely independent duplicate of a dictionary, especially one containing nested objects, a shallow copy will not be enough. You need a deep copy. This article walks through the difference between shallow and deep copying, shows you how to use copy.deepcopy(), and highlights the common pitfalls developers run into.
Shallow Copy vs. Deep Copy
A shallow copy of a dictionary creates a new dict object, but the values inside it still reference the same objects as the original. For flat dictionaries containing only immutable values like strings and integers, this is perfectly fine. The problem appears when your dictionary contains mutable objects like lists, sets, or other dictionaries as values.
A deep copy, on the other hand, recursively copies every object found within the dictionary. The result is a fully independent clone where modifying any nested structure in the copy has zero effect on the original.
Here is a quick demonstration of the difference:
In the shallow copy example, appending to shallow["scores"] also modified original["scores"] because both point to the same list object in memory. With deepcopy, the list is cloned entirely, so the original stays untouched.
Ways to Create Shallow Copies
Before reaching for deepcopy, it helps to know the common shallow copy techniques so you can recognize when they are sufficient:
All three produce a new dict object, but none of them recurse into nested values. For flat dictionaries with only immutable values, any of these approaches works perfectly.
How to Deep Copy a Dictionary
Python's built-in copy module provides the deepcopy function. It handles nested structures, circular references, and custom objects automatically.
When to Use Deep Copy
Use deepcopy in these situations:
- Nested structures: Your dictionary contains lists, dicts, sets, or other mutable objects as values.
- Preserving the original: You need to guarantee that mutations to the copy never leak back to the source.
- Snapshot before modification: You want to save a "before" state of configuration or data for comparison or rollback.
When You Do NOT Need Deep Copy
Deep copying is unnecessary (and wasteful) in several cases:
- Flat dictionaries with immutable values: A dictionary of strings and numbers can be safely shallow-copied.
- Immutable value types: Integers, strings, tuples, and frozensets cannot be mutated, so sharing references is harmless.
- Read-only usage: If you only need to read from the copy without modifying it, a shallow copy or even the original reference is fine.
Common Pitfalls
1. Using = instead of .copy() or deepcopy()
Assignment does not copy anything. Both variables point to the exact same dict object:
2. Assuming .copy() is deep
This is one of the most common bugs in Python. Developers call .copy() and assume nested structures are also cloned:
3. Performance overhead of deepcopy
deepcopy walks the entire object graph, tracking visited objects to handle circular references. For very large or deeply nested structures, this can be slow and memory-intensive. If performance matters and you know the structure is simple, consider a targeted approach like json.loads(json.dumps(data)) for JSON-serializable data, though this drops non-serializable types.
4. Custom objects inside dicts
If your dictionary contains instances of custom classes, deepcopy will attempt to copy them too. You can control this behavior by implementing __deepcopy__ on your class.
Summary
Use dict.copy(), dict(), or {**d} for flat dictionaries with immutable values. Reach for copy.deepcopy() whenever your dictionary contains nested mutable objects and you need a truly independent clone. Avoid the common trap of assuming that shallow copy handles nested structures, and be mindful of the performance cost when deep copying large object graphs.

