Merging two dictionaries means combining their key-value pairs into one dictionary. It's a common task when you're combining default settings with user overrides, merging API responses, or collecting data from multiple sources into one lookup table. Python has a few different ways to do it, and the "best" one depends on your Python version and whether you want to modify a dictionary in place.

Merge Dictionaries Using Dictionary Unpacking

The {**d1, **d2} syntax unpacks both dictionaries into a brand-new one. It works in any Python 3.5+ version.

defaults = {"theme": "light", "font_size": 14, "autosave": True}
overrides = {"font_size": 18, "language": "en"}

merged = {**defaults, **overrides}
print(merged)

Output:

{'theme': 'light', 'font_size': 18, 'autosave': True, 'language': 'en'}

Merge Dictionaries Using the | Operator (Python 3.9+)

Since Python 3.9, dictionaries support the | (merge) and |= (in-place merge) operators, which read more clearly than the unpacking syntax:

defaults = {"theme": "light", "font_size": 14, "autosave": True}
overrides = {"font_size": 18, "language": "en"}

merged = defaults | overrides
print(merged)

defaults |= overrides   # merges overrides directly into defaults
print(defaults)

Output:

{'theme': 'light', 'font_size': 18, 'autosave': True, 'language': 'en'}
{'theme': 'light', 'font_size': 18, 'autosave': True, 'language': 'en'}

In both approaches, the key thing to understand is collision order: whichever dictionary comes second wins on shared keys. That's why font_size ends up as 18 (from overrides) rather than 14 (from defaults) — if you reversed the order to {**overrides, **defaults}, you'd get 14 back instead. This is exactly the pattern you'd use to apply user preferences on top of a set of application defaults.

There's also the older defaults.update(overrides) method, which mutates defaults in place rather than creating a new dictionary — useful when you specifically want to avoid allocating a new object, but easy to misuse if you didn't mean to modify the original.