Python
dict
dictionary
union
duplicate

Union of dict objects in Python

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Python dictionaries can be combined in several ways, but the meaning of "union" needs one important clarification first: when duplicate keys exist, later values win unless you explicitly implement different merge logic. In modern Python, the cleanest syntax is the dictionary union operator |.

The Modern Operator: |

Python 3.9 added | for dictionaries. It creates a new dictionary containing keys from both operands.

python
1left = {"name": "Ada", "role": "engineer"}
2right = {"role": "lead", "team": "platform"}
3
4merged = left | right
5print(merged)

Output:

python
{'name': 'Ada', 'role': 'lead', 'team': 'platform'}

The key rule is that when both dictionaries contain the same key, the right-hand value wins. The originals are not modified.

In-Place Union With |=

If you want to update an existing dictionary rather than create a new one, use |=:

python
1config = {"host": "localhost", "port": 5432}
2override = {"port": 5433}
3
4config |= override
5print(config)

That mutates config directly. It is functionally similar to update, but the operator syntax is often easier to read when you are already thinking in terms of dictionary union.

Classic Approach: update

Before Python 3.9, the most common approach was update:

python
1left = {"a": 1, "b": 2}
2right = {"b": 20, "c": 3}
3
4result = left.copy()
5result.update(right)
6print(result)

This is still perfectly valid and widely used, especially when code must run on older Python versions.

The important detail is that update mutates the target dictionary, which is why the example copies left first.

Dictionary Unpacking

Another common pattern is dictionary unpacking:

python
1left = {"a": 1, "b": 2}
2right = {"b": 20, "c": 3}
3
4result = {**left, **right}
5print(result)

This also creates a new dictionary, and it follows the same overwrite rule: later values win.

For many readers, {**left, **right} was the nicest pre-3.9 syntax. In modern code, left | right usually communicates the intent more directly.

Merging More Than Two Dictionaries

All of these approaches generalize to several dictionaries.

python
1defaults = {"timeout": 30, "retries": 2}
2env = {"timeout": 10}
3user = {"retries": 5, "debug": True}
4
5result = defaults | env | user
6print(result)

The order matters. The rightmost value for any duplicate key is the one that survives.

That makes dictionary union a good fit for layered configuration where later sources intentionally override earlier ones.

Nested Dictionaries Are Not Deep-Merged

This is where many people get surprised. Dictionary union is shallow:

python
1left = {"db": {"host": "localhost", "port": 5432}}
2right = {"db": {"port": 5433}}
3
4print(left | right)

The result replaces the entire value for db rather than merging the inner dictionaries key by key.

If you need recursive merging, write explicit logic:

python
1def deep_merge(left, right):
2    result = left.copy()
3    for key, value in right.items():
4        if (
5            key in result
6            and isinstance(result[key], dict)
7            and isinstance(value, dict)
8        ):
9            result[key] = deep_merge(result[key], value)
10        else:
11            result[key] = value
12    return result
13
14
15print(deep_merge(left, right))

Deep merge is a different problem from ordinary dictionary union.

Which Method Should You Use

A practical guideline is:

  • use | in Python 3.9 and later for a clear non-mutating merge,
  • use |= or update when in-place mutation is intended,
  • use unpacking when supporting older code styles,
  • and use custom logic when duplicate keys need more than "right-hand side wins."

The best choice is mostly about readability, Python version, and whether mutation is acceptable.

Common Pitfalls

The most common mistake is forgetting that duplicate keys are overwritten by the right-hand dictionary. If you expected both values to be preserved somehow, ordinary union is the wrong operation.

Another mistake is assuming the merge is deep. It is not. Nested dictionaries are replaced at the top level unless you implement recursive behavior yourself.

Developers also sometimes mutate a source dictionary accidentally with update when they really wanted a new result. Use copy first or prefer | when you want non-mutating behavior.

Finally, be careful when merging configuration from multiple sources. The order of operations determines which value survives.

Summary

  • In modern Python, dict_a | dict_b is the clearest non-mutating dictionary union.
  • For duplicate keys, the right-hand value wins.
  • '|= and update perform in-place updates.'
  • Dictionary union is shallow, not recursive.
  • Use a custom deep-merge function when nested dictionaries must be combined key by key.

Course illustration
Course illustration

All Rights Reserved.