deep copy
python dict
python programming
dictionary copying
python tips

Deep copy of a dict in python

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

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:

python
1import copy
2
3original = {
4    "name": "Alice",
5    "scores": [95, 87, 92],
6    "meta": {"level": 3, "tags": ["active", "verified"]}
7}
8
9# Shallow copy
10shallow = original.copy()
11shallow["scores"].append(100)
12print(original["scores"])  # [95, 87, 92, 100] -- original is affected!
13
14# Deep copy
15deep = copy.deepcopy(original)
16deep["scores"].append(50)
17print(original["scores"])  # [95, 87, 92, 100] -- original is NOT affected

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:

python
1# Method 1: dict.copy()
2shallow1 = original.copy()
3
4# Method 2: dict() constructor
5shallow2 = dict(original)
6
7# Method 3: unpacking
8shallow3 = {**original}

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.

python
1import copy
2
3config = {
4    "database": {
5        "host": "localhost",
6        "port": 5432,
7        "replicas": ["replica-1", "replica-2"]
8    },
9    "cache": {
10        "ttl": 300,
11        "backends": ["redis", "memcached"]
12    }
13}
14
15config_backup = copy.deepcopy(config)
16
17# Modify the backup freely
18config_backup["database"]["replicas"].append("replica-3")
19config_backup["cache"]["ttl"] = 600
20
21# Original remains unchanged
22print(config["database"]["replicas"])  # ["replica-1", "replica-2"]
23print(config["cache"]["ttl"])          # 300

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:

python
1a = {"key": [1, 2, 3]}
2b = a           # No copy at all
3b["key"].append(4)
4print(a["key"]) # [1, 2, 3, 4]

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:

python
1a = {"key": [1, 2, 3]}
2b = a.copy()
3b["key"].append(4)
4print(a["key"])  # [1, 2, 3, 4] -- surprise!

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.


Related reading
Course
Intermediate
27 lessons
15 hours
DSA Fundamentals

Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

All Rights Reserved.