Back to Blog
Python

Python Dictionary Merge: Methods and Tradeoffs

python dictionary merge: Learn how to merge dictionaries in Python using update(), unpacking and the union operator, with tradeoffs for each approach.

pythondictionariesmergedata-structurespython-tips
Illustration of merging two dictionary objects into a single combined dictionary with keys and values.

Combining two dictionaries is a common operation in Python, and the language offers several ways to perform a python dictionary merge. The choice affects whether you mutate an existing dictionary or create a new one, how key collisions are resolved, and how readable the code is for your team.

The Core Problem: Combining Two Dictionaries

When you need to merge two dictionaries, the first decision is whether the original dictionary should be modified or preserved. The second decision is which value wins when both dictionaries contain the same key. These two properties define the behavior of every merge method in Python. For example, given d1 = {'a': 1, 'b': 2} and d2 = {'b': 3, 'c': 4}, a merge could produce {'a': 1, 'b': 3, 'c': 4} if d2 takes precedence, or {'a': 1, 'b': 2, 'c': 4} if d1 does. Most merge methods give precedence to the right-hand dictionary, but the way they do it differs in mutation and return value.

Using update() to Merge In Place

The update() method modifies the dictionary it is called on. It takes another dictionary or an iterable of key-value pairs and adds or overwrites keys from the argument. Because it changes the original object, it returns None. This is useful when you are building a configuration dictionary incrementally and do not need to keep the original version.

d1 = {'a': 1, 'b': 2} d2 = {'b': 3, 'c': 4} d1.update(d2) print(d1) # {'a': 1, 'b': 3, 'c': 4}

The method works with any mapping, including dict subclasses and objects that implement the mapping protocol. It also accepts keyword arguments, so d1.update(b=3, c=4) is equivalent. The main limitation is that update() does not return the merged dictionary, so you cannot chain it or use it in an expression that expects a dictionary.

Dictionary Unpacking with {**d1, **d2}

The double-star unpacking syntax creates a new dictionary without modifying either input. This is often the most readable way to merge two dictionaries when you want a fresh object and you know the keys are strings or hashable types.

merged = {**d1, **d2} print(merged) # {'a': 1, 'b': 3, 'c': 4} print(d1) # {'a': 1, 'b': 2} unchanged

The order of unpacking matters: later dictionaries override earlier ones. You can also mix in literal key-value pairs, such as {**d1, 'b': 10, **d2}, which gives you fine-grained control over precedence. This syntax works in Python 3.5 and later, and it is the most common approach for merging dictionaries in code that must support older Python versions.

The Union Operator | for Dictionaries

Python 3.9 introduced the | operator for dictionaries, which returns a new dictionary that combines the two operands. The left operand provides the base, and the right operand overwrites any duplicate keys.

merged = d1 | d2 print(merged) # {'a': 1, 'b': 3, 'c': 4}

There is also the augmented assignment version, d1 |= d2, which updates d1 in place, similar to update(). The operator is concise and reads naturally, especially when you are merging more than two dictionaries: result = d1 | d2 | d3. However, it requires Python 3.9 or newer, so it is not available in projects that still target Python 3.8 or earlier.

Merging with dict() Constructor and Keyword Arguments

The dict() constructor can also merge dictionaries when you pass another mapping as the first argument and then provide keyword arguments. The keyword arguments are added after the mapping, so they take precedence.

merged = dict(d1, **d2) print(merged) # {'a': 1, 'b': 3, 'c': 4}

This approach has a significant constraint: the keys in d2 must be strings, because they are passed as keyword arguments. If d2 contains integer keys or tuples, this will raise a TypeError. For that reason, this method is rarely the best choice for general-purpose merging. It can be useful when you know the keys are valid Python identifiers and you want to add a few overrides explicitly.

Handling Nested Dictionaries and Overlapping Keys

All of the methods described so far perform a shallow merge. If a key appears in both dictionaries and its value is itself a dictionary, the value from the right-hand dictionary replaces the entire nested dictionary. It does not recursively merge the inner keys. For example:

d1 = {'config': {'host': 'localhost', 'port': 8080}} d2 = {'config': {'host': 'example.com'}} merged = {**d1, **d2} print(merged) # {'config': {'host': 'example.com'}}

The port key is lost. If you need to merge nested dictionaries recursively, you must write a custom function or use a library that provides deep merge semantics. This is a common source of bugs when merging configuration files or API response payloads, because the expectation is often that nested values will be combined rather than replaced.

Performance and Memory Considerations

The performance difference between these methods is usually small for typical dictionary sizes, but the mutation behavior has a direct impact on memory usage. update() and |= modify the existing dictionary in place, so they do not allocate a new dictionary object. The unpacking and | operator create a new dictionary, which means they allocate memory for the entire merged result. If you are merging large dictionaries in a loop, repeatedly creating new dictionaries can become a measurable cost. In such cases, using update() on a pre-allocated dictionary may be more efficient.

Another consideration is that update() and |= can be used to merge an arbitrary number of dictionaries in a loop without creating intermediate copies. For example, you can start with an empty dictionary and call update() for each source. This is a common pattern when building a configuration from multiple layers.

Choosing the Right Merge Method

The decision comes down to three questions: Do you need to preserve the original dictionaries? What Python version are you targeting? And do you need to handle non-string keys? If you need a new dictionary and you are on Python 3.9+, the | operator is the most readable. If you are on an older version, {**d1, **d2} is the standard choice. If you want to modify an existing dictionary, update() is the direct method. Avoid dict(d1, **d2) unless you are certain all keys are strings. For nested merges, none of the built-in methods work; you need a recursive implementation.

When you are merging more than two dictionaries, you can chain the operators or unpacking, but be aware that each operation creates an intermediate dictionary. For a small number of dictionaries this is irrelevant, but for a long list, consider using a loop with update() to avoid repeated allocation.

python dictionary merge: Practical Usage and Code Examples | RYUSLOG DEV