Python
Dictionary
Concatenation
Coding
Programming

How to concatenate two dictionaries to create a new one?

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

Introduction

Combining dictionaries in Python is simple for flat key-value pairs, but details matter when keys overlap or values are nested. The wrong merge method can silently overwrite data or mutate objects you expected to keep unchanged. This guide compares reliable merge patterns and when to use each one.

Use the Merge Operator for Readable New Dictionaries

In modern Python, the | operator creates a new dictionary from two inputs. If both dictionaries contain the same key, the right-hand dictionary wins.

python
1left = {"host": "localhost", "port": 5432, "ssl": False}
2right = {"port": 5433, "timeout": 30}
3
4merged = left | right
5
6print("left:", left)
7print("right:", right)
8print("merged:", merged)

Output behavior:

  • left and right remain unchanged.
  • merged["port"] becomes 5433 because right side overrides left side.

This is usually the cleanest syntax for configuration layering, such as defaults plus environment-specific overrides.

Support Older Python With Unpacking

If you need compatibility with Python 3.5 and later, dictionary unpacking provides similar behavior.

python
1defaults = {"retries": 3, "backoff": 1.0}
2override = {"backoff": 2.5}
3
4merged = {**defaults, **override}
5print(merged)

Unpacking creates a new dictionary and follows the same key precedence rule where later values override earlier ones.

For dynamic multi-source merges, combine many dictionaries in order:

python
1base = {"log_level": "INFO", "region": "us-east-1"}
2team = {"log_level": "DEBUG"}
3user = {"region": "ca-central-1"}
4
5merged = {**base, **team, **user}
6print(merged)

The final result reflects the last value for each repeated key.

Use copy Plus update When You Need In-Place Flow

update mutates a dictionary, which can be efficient in imperative pipelines. If you still need a new dictionary, clone first.

python
1source_a = {"a": 1, "b": 2}
2source_b = {"b": 20, "c": 30}
3
4result = source_a.copy()
5result.update(source_b)
6
7print("source_a:", source_a)
8print("result:", result)

This style is explicit in multi-step code where you progressively enrich one working object. It is also convenient when merge inputs are produced conditionally.

Handle Nested Dictionaries With Deep Merge Logic

All basic merge methods are shallow. If both sides contain nested dictionaries under the same key, the entire nested object from the right side replaces the left side value.

When you need recursive behavior, implement a deep merge function:

python
1from copy import deepcopy
2
3
4def deep_merge(left: dict, right: dict) -> dict:
5    result = deepcopy(left)
6    for key, value in right.items():
7        if (
8            key in result
9            and isinstance(result[key], dict)
10            and isinstance(value, dict)
11        ):
12            result[key] = deep_merge(result[key], value)
13        else:
14            result[key] = deepcopy(value)
15    return result
16
17
18if __name__ == "__main__":
19    a = {
20        "db": {"host": "localhost", "pool": {"min": 2, "max": 10}},
21        "feature": {"enabled": False},
22    }
23    b = {
24        "db": {"pool": {"max": 30}},
25        "feature": {"enabled": True},
26    }
27
28    merged = deep_merge(a, b)
29    print(merged)

This approach protects nested data and avoids mutation side effects through deep copies.

Choose Merge Semantics Deliberately

Before choosing syntax, define merge rules clearly:

  • should right side always override
  • should missing keys be preserved
  • should nested dictionaries merge recursively
  • should lists append, replace, or deduplicate

Encoding these rules in one utility function prevents inconsistent behavior across modules.

For application configuration, merge order should mirror precedence levels. For example: defaults, environment file, secret store, runtime flags. Keeping this order explicit improves predictability and debugging.

Common Pitfalls

  • Assuming merges are deep when Python built-in merge methods are shallow.
  • Mutating a source dictionary with update when immutable behavior was expected.
  • Relying on implicit key precedence instead of documenting source priority.
  • Merging dictionaries that contain mutable nested structures without copying.
  • Forgetting version compatibility when using the | operator on older Python versions.

Summary

  • Use | for clear new-dictionary merges in modern Python.
  • Use unpacking syntax for broad Python 3 compatibility.
  • Use copy plus update for explicit stepwise mutation workflows.
  • Implement deep merge when nested dictionary values must combine recursively.
  • Define and document precedence rules to avoid silent data loss.

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.