Question

How to Merge Two Dictionaries in a Single Expression in Python

pythondictionarymerge

Question

I want to merge two Python dictionaries into a new dictionary using a single expression.

x = {'a': 1, 'b': 2}
y = {'b': 3, 'c': 4}
z = merge(x, y)

print(z)
# {'a': 1, 'b': 3, 'c': 4}

If the same key exists in both dictionaries, the value from y should overwrite the value from x. What is the correct Pythonic way to do this?

Short Answer

By the end of this page, you will understand how dictionary merging works in Python, how key conflicts are resolved, and how to combine dictionaries into a new one using modern and older Python syntax. You will also see common mistakes, practical examples, and patterns used in real codebases.

Concept

In Python, a dictionary stores data as key-value pairs. Merging dictionaries means combining the pairs from two or more dictionaries into one new dictionary.

The key rule in your question is:

  • keep all keys from both dictionaries
  • if the same key appears in both, the value from the later dictionary should win

For example:

x = {'a': 1, 'b': 2}
y = {'b': 3, 'c': 4}

When merged:

{'a': 1, 'b': 3, 'c': 4}

The key 'b' exists in both dictionaries, so the value from y replaces the value from x.

This matters in real programming because dictionaries are often used for:

  • configuration settings
  • API response data
  • user input
  • default values overridden by custom values
  • combining computed results

Python gives you several ways to merge dictionaries. The best choice depends on your Python version and whether you want to create a new dictionary or modify an existing one.

Common modern approaches are:

z = x | y

and:

z = {**x, **y}

Both create a new dictionary, and in both cases y overrides matching keys from x.

Mental Model

Think of a dictionary like a labeled set of sticky notes.

  • x is one board of notes
  • y is another board of notes
  • merging means copying all notes onto a new board

If both boards have a note with the same label, you cannot keep both under the same label. The later board's note replaces the earlier one.

So when you merge x and then y, you are saying:

  • start with everything from x
  • place everything from y on top
  • if y uses a label that already exists, its note covers the old one

That is why the value from y wins when keys overlap.

Take Quiz

Syntax and Examples

Modern syntax

In Python 3.9 and later, you can use the dictionary merge operator:

x = {'a': 1, 'b': 2}
y = {'b': 3, 'c': 4}

z = x | y
print(z)
# {'a': 1, 'b': 3, 'c': 4}

This creates a new dictionary.

Compatible syntax for older Python versions

In Python 3.5 and later, dictionary unpacking is a common solution:

x = {'a': 1, 'b': 2}
y = {'b': 3, 'c': 4}

z = {**x, **y}
print(z)
# {'a': 1, 'b': 3, 'c': 4}

This also creates a new dictionary, and later unpacked dictionaries override earlier ones.

Updating an existing dictionary

If you want to modify one dictionary in place instead of creating a new one:

x = {'a': 1, 'b': 2}
y = {'b': 3, 'c': 4}

x.update(y)
print(x)
# {'a': 1, 'b': 3, 'c': 4}

This changes x directly.

Multiple dictionaries

You can merge more than two dictionaries:

defaults = {'theme': 'light', 'language': 'en'}
user_settings = {'theme': 'dark'}
runtime_overrides = {'language': 'fr'}

settings = defaults | user_settings | runtime_overrides
print(settings)
# {'theme': 'dark', 'language': 'fr'}

The rightmost dictionary has the highest priority.

Why the order matters

x = {'b': 2}
y = {'b': 3}

print(x | y)  # {'b': 3}
print(y | x)  # {'b': 2}

The later dictionary wins on duplicate keys.

Step by Step Execution

Consider this example:

x = {'a': 1, 'b': 2}
y = {'b': 3, 'c': 4}
z = {**x, **y}

Here is what happens step by step:

  1. Python starts building a new empty dictionary for z.

  2. **x adds all key-value pairs from x:

    {'a': 1, 'b': 2}
    
  3. **y then adds all key-value pairs from y.

  4. Python sees that 'b' already exists.

  5. The new value from y replaces the old value from x.

  6. 'c' is new, so it gets added.

Final result:

{'a': 1, 'b': 3, 'c': 4}

The same logic applies to:

z = x | y

Python combines keys from left to right, and later values override earlier ones.

Trace example

base = {'host': 'localhost', 'port': 5000}
overrides = {'port': 8000}
config = base | overrides
print(config)

Step by step:

  1. Start with {'host': 'localhost', 'port': 5000}
  2. Add {'port': 8000}
  3. Key 'port' already exists
  4. Replace 5000 with 8000
  5. Final dictionary becomes:
{'host': 'localhost', 'port': 8000}

Real World Use Cases

Dictionary merging is very common in Python programs.

Configuration systems

You may have default settings and user overrides:

default_config = {'debug': False, 'port': 5000}
user_config = {'port': 8000}
config = default_config | user_config

API data processing

You may combine data from different sources:

user = {'id': 1, 'name': 'Ava'}
profile = {'name': 'Ava Smith', 'city': 'London'}
full_data = user | profile

Form or request handling

You might start with defaults, then apply submitted values:

defaults = {'newsletter': False, 'role': 'user'}
submitted = {'newsletter': True}
result = defaults | submitted

Test setup

Tests often begin with a base object and override only one or two values:

base_payload = {'status': 'active', 'admin': False}
test_payload = base_payload | {'admin': True}

Data transformation pipelines

While processing records, you may keep old fields and add derived ones:

record = {'price': 100, 'tax_rate': 0.2}
enriched = record | {'tax': 20}
Take Quiz

Real Codebase Usage

In real projects, developers use dictionary merging as part of larger patterns.

Defaults plus overrides

A very common pattern is:

settings = defaults | env_values | cli_args

This clearly shows precedence:

  • defaults are lowest priority
  • environment values override defaults
  • command-line arguments override everything

Building new objects without mutating inputs

In production code, creating a new dictionary is often safer than changing an existing one:

new_state = old_state | {'loading': False}

This avoids unexpected side effects.

Guarded merging

Sometimes you only merge if extra values are present:

result = base.copy()
if extra_data:
    result |= extra_data

Validation before merge

Developers often validate incoming data before merging it:

def apply_overrides(config, overrides):
    allowed = {'host', 'port', 'debug'}
    clean = {k: v for k, v in overrides.items() if k in allowed}
    return config | clean

Merging in function calls

Dictionary unpacking is often used when passing keyword arguments:

base_options = {'timeout': 10, 'retries': 3}
request_options = {**base_options, 'timeout': 30}

This keeps code readable and explicit.

Common Mistakes

1. Accidentally mutating the original dictionary

Broken expectation:

x = {'a': 1, 'b': 2}
y = {'b': 3}

x.update(y)
print(x)  # x was changed

If you need a new dictionary, use:

z = x | y

or:

z = {**x, **y}

2. Expecting both values for duplicate keys to be kept

A dictionary cannot store the same key twice.

x = {'b': 2}
y = {'b': 3}
z = x | y
print(z)
# {'b': 3}

If you need both values, use a different structure such as a list:

{'b': [2, 3]}

3. Reversing the order

Broken logic:

x = {'b': 2}
y = {'b': 3}
z = y | x
print(z)
# {'b': 2}

Remember: right side wins.

4. Using syntax not supported by your Python version

This works only in Python 3.9+:

z = x | y

If you are on Python 3.5 to 3.8, use:

z = {**x, **y}

5. Forgetting that nested dictionaries are not deeply merged

x = {'db': {'host': 'localhost', 'port': 5432}}
y = {'db': {'port': 5433}}
z = x | y
print(z)
# {'db': {'port': 5433}}

The whole nested value for 'db' is replaced. This is a shallow merge, not a deep merge.

6. Trying to call a non-existent built-in merge() function

Python has no built-in function like this:

z = merge(x, y)  # Not valid Python built-in behavior

Use supported syntax instead.

Comparisons

ApproachCreates new dictionary?Modifies existing dictionary?Python versionConflict rule
`xy`YesNo3.9+
{**x, **y}YesNo3.5+Later unpack wins
x.update(y)NoYes, x changesAll modern Python versionsy overwrites x
x.copy(); x.update(y)YesOnly the copy changesAll modern Python versionsy overwrites copy

| vs update()

  • Use | when you want a new dictionary.
  • Use update() when you want to change the existing dictionary.

| vs {**x, **y}

  • Both create a new dictionary.
  • | is cleaner and more readable in Python 3.9+.
  • {**x, **y} is useful for compatibility with older Python versions.

Shallow merge vs deep merge

TypeWhat happens
Shallow mergeTop-level keys are merged; nested dictionaries are replaced
Deep mergeNested dictionaries are merged recursively

Normal dictionary merging in Python is shallow.

Take Quiz

Cheat Sheet

Quick syntax

Python 3.9+

z = x | y

Python 3.5+

z = {**x, **y}

Modify existing dictionary

x.update(y)

Rules

  • Dictionaries store unique keys.
  • When keys overlap, the later value replaces the earlier one.
  • x | y means y has higher priority than x.
  • Merging dictionaries normally performs a shallow merge.

Examples

{'a': 1} | {'b': 2}
# {'a': 1, 'b': 2}
{'a': 1} | {'a': 9}
# {'a': 9}
{**{'a': 1}, **{'a': 9, 'b': 2}}
# {'a': 9, 'b': 2}

Safe pattern when you do not want mutation

result = original | overrides

Watch out for nested dictionaries

x = {'settings': {'theme': 'light', 'font': 'small'}}
y = {'settings': {'theme': 'dark'}}

print(x | y)
# {'settings': {'theme': 'dark'}}

The entire nested value is replaced.

FAQ

How do I merge two dictionaries in Python without changing the originals?

Use x | y in Python 3.9+ or {**x, **y} in Python 3.5+. Both create a new dictionary.

Which dictionary wins when keys overlap?

The later dictionary wins. In x | y, the value from y replaces the value from x for duplicate keys.

Is dict.update() the same as merging?

It is similar in result, but it modifies the dictionary in place instead of creating a new one.

Does Python have a built-in merge(x, y) function?

No. Python uses operators and methods like |, unpacking, and update() instead.

Can I merge more than two dictionaries at once?

Yes.

result = a | b | c

or:

result = {**a, **b, **c}

Does dictionary merging work recursively for nested dictionaries?

No, not by default. Standard merging is shallow, so nested dictionaries are replaced, not recursively combined.

What is the most readable way to merge dictionaries in modern Python?

In Python 3.9+, x | y is usually the clearest option.

What should I use if I need compatibility with older Python versions?

Use {**x, **y} for Python 3.5+ compatibility.

Take Quiz

Mini Project

Description

Build a small Python utility that combines default application settings with user-provided overrides. This demonstrates practical dictionary merging and shows how later values replace earlier ones.

Goal

Create a function that returns a new configuration dictionary where user settings override default settings.

Requirements

  1. Create a dictionary of default settings.
  2. Create a second dictionary containing user overrides.
  3. Merge them into a new dictionary without changing the original defaults.
  4. Print the original dictionaries and the merged result.
  5. Show that overlapping keys use the value from the user overrides.
Take Quiz

Keep learning

Related questions

View more