How to Compare Two Dictionaries in Python
Comparing dictionaries is a common task in Python, whether you're validating configurations, tracking data changes, writing tests, or synchronizing records. Python dictionaries can be compared for equality, checked for specific differences, or analyzed to find exactly which keys and values changed.
In this guide, you'll learn multiple methods to compare two dictionaries in Python, from simple equality checks to detailed difference analysis with practical examples.
Using the == Operator (Simplest Method)
The most straightforward way to compare two dictionaries is the == operator. It returns True if both dictionaries have the same keys and the same values, regardless of insertion order.
d1 = {'a': 1, 'b': 2, 'c': 3}
d2 = {'c': 3, 'a': 1, 'b': 2}
d3 = {'a': 1, 'b': 99, 'c': 3}
print(d1 == d2) # Same content, different order
print(d1 == d3) # Different value for key 'b'
Output:
True
False
Python dictionaries compare by content, not insertion order, so d1 == d2 returns True even though the keys were defined in a different sequence.
The == operator also works with nested dictionaries. It recursively compares all keys and values at every level:
d1 = {'user': {'name': 'Alice', 'age': 30}}
d2 = {'user': {'name': 'Alice', 'age': 30}}
print(d1 == d2) # True
Finding Specific Differences
While == tells you whether dictionaries differ, it doesn't tell you what differs. Here are several ways to identify the exact differences.
Finding Added, Removed, and Changed Keys
Use set operations on dictionary keys to categorize differences:
d1 = {'a': 1, 'b': 2, 'c': 3}
d2 = {'b': 2, 'c': 99, 'd': 4}
keys_1 = set(d1.keys())
keys_2 = set(d2.keys())
added = keys_2 - keys_1
removed = keys_1 - keys_2
common = keys_1 & keys_2
changed = {k for k in common if d1[k] != d2[k]}
unchanged = {k for k in common if d1[k] == d2[k]}
print(f"Added: {added}")
print(f"Removed: {removed}")
print(f"Changed: {changed}")
print(f"Unchanged: {unchanged}")
Output:
Added: {'d'}
Removed: {'a'}
Changed: {'c'}
Unchanged: {'b'}
This approach gives you a clear breakdown of exactly what changed between the two dictionaries.
Building a Reusable Diff Function
For production code, wrap the comparison logic into a reusable function:
def dict_diff(d1, d2):
"""Compare two dictionaries and return detailed differences."""
keys_1, keys_2 = set(d1), set(d2)
return {
'added': {k: d2[k] for k in keys_2 - keys_1},
'removed': {k: d1[k] for k in keys_1 - keys_2},
'changed': {
k: {'old': d1[k], 'new': d2[k]}
for k in keys_1 & keys_2 if d1[k] != d2[k]
},
'unchanged': {k: d1[k] for k in keys_1 & keys_2 if d1[k] == d2[k]}
}
config_v1 = {'host': 'localhost', 'port': 8080, 'debug': True, 'log_level': 'INFO'}
config_v2 = {'host': 'localhost', 'port': 9090, 'debug': False, 'workers': 4}
diff = dict_diff(config_v1, config_v2)
for category, items in diff.items():
if items:
print(f"\n{category.upper()}:")
for key, value in items.items():
print(f" {key}: {value}")
Output:
ADDED:
workers: 4
REMOVED:
log_level: INFO
CHANGED:
debug: {'old': True, 'new': False}
port: {'old': 8080, 'new': 9090}
UNCHANGED:
host: localhost
Using a Loop for Manual Comparison
For simple scripts or when you want full control over the comparison logic, a manual loop works well:
d1 = {'a': 1, 'b': 2, 'c': 3}
d2 = {'a': 1, 'b': 2, 'c': 3}
def are_dicts_equal(dict1, dict2):
"""Check if two dictionaries are equal using manual iteration."""
if len(dict1) != len(dict2):
return False
for key in dict1:
if key not in dict2 or dict1[key] != dict2[key]:
return False
return True
print(are_dicts_equal(d1, d2))
Output:
True
How it works:
- First, check if the lengths differ. If they do, the dictionaries can't be equal.
- Iterate through each key in
dict1and verify it exists indict2with the same value. - If any mismatch is found, return
Falseimmediately. If the loop completes, returnTrue.
This approach is functionally equivalent to == for flat dictionaries. However, it won't handle nested dictionaries correctly unless you add recursive logic. For nested structures, prefer == or DeepDiff.
Using DeepDiff for Complex Comparisons
For nested dictionaries, large data structures, or cases where you need detailed reports, the third-party deepdiff library is extremely powerful:
pip install deepdiff
from deepdiff import DeepDiff
d1 = {
'user': {
'name': 'Alice',
'settings': {'theme': 'dark', 'language': 'en'}
},
'version': 1
}
d2 = {
'user': {
'name': 'Alice',
'settings': {'theme': 'light', 'language': 'en', 'notifications': True}
},
'version': 2
}
diff = DeepDiff(d1, d2)
for change_type, details in diff.items():
print(f"\n{change_type}:")
for key, value in details.items():
print(f" {key}: {value}")
Output:
values_changed:
root['user']['settings']['theme']: {'new_value': 'light', 'old_value': 'dark'}
root['version']: {'new_value': 2, 'old_value': 1}
dictionary_item_added:
root['user']['settings']['notifications']: True
DeepDiff automatically handles nested structures, lists, sets, and other complex data types, providing precise paths to every change.
Comparing Only Specific Keys
Sometimes you only care about certain keys, not the entire dictionary:
def compare_keys(d1, d2, keys):
"""Compare two dictionaries on specific keys only."""
results = {}
for key in keys:
val1 = d1.get(key)
val2 = d2.get(key)
results[key] = {
'equal': val1 == val2,
'values': (val1, val2)
}
return results
user_v1 = {'name': 'Alice', 'age': 30, 'email': 'alice@old.com', 'role': 'user'}
user_v2 = {'name': 'Alice', 'age': 31, 'email': 'alice@new.com', 'role': 'admin'}
# Only compare name and age
result = compare_keys(user_v1, user_v2, ['name', 'age'])
for key, info in result.items():
status = "✅ same" if info['equal'] else f"❌ changed: {info['values'][0]} → {info['values'][1]}"
print(f" {key}: {status}")
Output:
name: ✅ same
age: ❌ changed: 30 → 31
Comparing Dictionaries with Different Key Sets
The == operator correctly handles dictionaries with different key sets. They are simply not equal:
d1 = {'a': 1, 'b': 2}
d2 = {'a': 1, 'b': 2, 'c': 3}
print(d1 == d2) # False: d2 has an extra key
Output:
False
However, if you're comparing value by value using a loop, forgetting to check for extra keys in the second dictionary is a common mistake:
d1 = {'a': 1, 'b': 2}
d2 = {'a': 1, 'b': 2, 'c': 3}
# ❌ Wrong: only checks keys in d1, ignores extra keys in d2
def broken_compare(d1, d2):
for key in d1:
if d1[key] != d2.get(key):
return False
return True
print(broken_compare(d1, d2)) # True: incorrectly ignores 'c' in d2
Output:
True
Always check that both dictionaries have the same number of keys before iterating, or check keys from both sides.
Quick Comparison of Methods
| Method | Detects Differences | Shows Details | Handles Nesting | External Dependency |
|---|---|---|---|---|
== operator | ✅ Equal or not | ❌ | ✅ | None |
| Set operations on keys | ✅ Added/removed/changed | ✅ | ❌ | None |
dict_diff() function | ✅ Full categorization | ✅ | ❌ (flat only) | None |
| Manual loop | ✅ Equal or not | ❌ | ❌ (without recursion) | None |
DeepDiff | ✅ Full categorization | ✅ Detailed paths | ✅ | deepdiff |
Conclusion
Python provides several ways to compare dictionaries depending on what level of detail you need:
==operator is the simplest and most efficient way to check if two dictionaries are identical. It handles nested structures and is order-independent.- Set operations on keys let you categorize differences into added, removed, changed, and unchanged keys without any external libraries.
- A reusable diff function provides structured output suitable for logging, reporting, or further processing.
DeepDiffis the best choice for complex nested dictionaries where you need precise change paths and detailed reports.
For most everyday comparisons, == is all you need. When you need to know what changed, not just whether something changed, use set operations or DeepDiff to get actionable details.