Table of contents
Debug code issues

How to merge two dictionaries in Python

Jun 6, 2025
 ・ by  
Claude and the Anthropic Team
Table of contents
H2 Link Template
Try Claude

Merging Python dictionaries combines key-value pairs from multiple sources into a single dictionary. Python offers several built-in methods to merge dictionaries efficiently, including the update() method and the | union operator.

This guide covers essential merging techniques, practical applications, and debugging strategies, with code examples created using Claude, an AI assistant built by Anthropic.

Using the update() method

dict1 = {'a': 1, 'b': 2}
dict2 = {'c': 3, 'd': 4}
dict1.update(dict2)
print(dict1)
{'a': 1, 'b': 2, 'c': 3, 'd': 4}

The update() method provides a straightforward way to merge dictionaries by adding key-value pairs from one dictionary into another. When you call dict1.update(dict2), Python modifies dict1 in place by incorporating all entries from dict2.

This approach offers several practical advantages:

  • Memory efficiency since it modifies the existing dictionary rather than creating a new one
  • Clean syntax that clearly communicates the merge operation's direction
  • Predictable handling of duplicate keys where values from the second dictionary take precedence

Common dictionary merging techniques

Beyond the update() method, Python offers several elegant merging techniques including the ** unpacking operator, dict() constructor, and dictionary comprehension—each providing unique advantages for specific use cases.

Using the ** unpacking operator

dict1 = {'a': 1, 'b': 2}
dict2 = {'c': 3, 'd': 4}
merged_dict = {**dict1, **dict2}
print(merged_dict)
{'a': 1, 'b': 2, 'c': 3, 'd': 4}

The ** unpacking operator creates a new dictionary by extracting all key-value pairs from existing dictionaries. This method preserves the original dictionaries while combining their contents into a fresh dictionary object.

  • The order matters—later dictionaries override any duplicate keys from earlier ones
  • The syntax is clean and readable, making it ideal for merging multiple dictionaries in a single line
  • Python creates the merged dictionary in memory, unlike update() which modifies in place

This approach particularly shines when you need to preserve the original dictionaries or merge three or more dictionaries at once. The resulting merged_dict contains all key-value pairs while leaving dict1 and dict2 unchanged.

Using the dict() constructor

dict1 = {'a': 1, 'b': 2}
dict2 = {'c': 3, 'd': 4}
merged_dict = dict(dict1)
merged_dict.update(dict2)
print(merged_dict)
{'a': 1, 'b': 2, 'c': 3, 'd': 4}

The dict() constructor method combines the safety of creating a new dictionary with the flexibility of in-place updates. This approach first creates a copy of dict1 using dict(), then applies update() to add entries from dict2.

  • Preserves the original dict1 by working with a copy instead of modifying it directly
  • Provides more explicit control over the merging process compared to unpacking operators
  • Works reliably across all Python versions, making it a dependable choice for legacy code

This technique particularly suits situations where you need to maintain the original dictionary while performing multiple merge operations or when working with dictionaries that might contain special key types.

Using dictionary comprehension

dict1 = {'a': 1, 'b': 2}
dict2 = {'c': 3, 'd': 4}
merged_dict = {k: v for d in [dict1, dict2] for k, v in d.items()}
print(merged_dict)
{'a': 1, 'b': 2, 'c': 3, 'd': 4}

Dictionary comprehension offers a concise, one-line approach to merge dictionaries by iterating through a list of input dictionaries. The syntax {k: v for d in [dict1, dict2] for k, v in d.items()} creates key-value pairs from each dictionary in sequence.

  • The outer loop for d in [dict1, dict2] selects each source dictionary
  • The inner loop for k, v in d.items() extracts individual key-value pairs
  • Later dictionaries override earlier ones when keys overlap

While this method creates elegant, readable code, it may use more memory than update() since it generates a new dictionary. Consider using dictionary comprehension when code clarity matters more than performance optimization.

Advanced dictionary merging techniques

Beyond the foundational merging techniques, Python offers specialized tools like collections.ChainMap, the | operator, and deep merging strategies that handle complex dictionary structures with greater precision and flexibility.

Using collections.ChainMap

from collections import ChainMap
dict1 = {'a': 1, 'b': 2}
dict2 = {'c': 3, 'b': 4}
chain_map = ChainMap(dict2, dict1)
print(dict(chain_map))
{'a': 1, 'b': 4, 'c': 3}

ChainMap creates a view of multiple dictionaries that maintains their original structure while providing unified access. When you create a ChainMap(dict2, dict1), Python searches through the dictionaries in order until it finds the first matching key.

The order of dictionaries in ChainMap determines key precedence. In our example, dict2 comes first. This means its value for the key 'b' (4) overrides the value from dict1 (2) in the final output.

  • Preserves the original dictionaries instead of modifying them
  • Searches keys from left to right in the specified dictionary order
  • Memory efficient because it doesn't create a new merged dictionary unless explicitly converted using dict()

Using the | operator (Python 3.9+)

dict1 = {'a': 1, 'b': 2}
dict2 = {'c': 3, 'b': 4}
merged_dict = dict1 | dict2
print(merged_dict)
{'a': 1, 'b': 4, 'c': 3}

Python 3.9 introduced the | operator as an elegant way to merge dictionaries. This union operator creates a new dictionary while keeping the originals unchanged, similar to how set unions work.

  • The rightmost dictionary (dict2) takes precedence for duplicate keys. In our example, dict2's value for 'b' (4) overrides dict1's value (2)
  • The syntax is remarkably clean compared to other merging methods. It reads naturally from left to right
  • You can chain multiple dictionaries using the operator: dict1 | dict2 | dict3

The | operator combines simplicity with readability. It's particularly useful when you need a quick merge without modifying the source dictionaries.

Deep merging nested dictionaries

def deep_merge(d1, d2):
    result = d1.copy()
    for k, v in d2.items():
        if k in result and isinstance(result[k], dict) and isinstance(v, dict):
            result[k] = deep_merge(result[k], v)
        else:
            result[k] = v
    return result

dict1 = {'a': 1, 'b': {'x': 10, 'y': 20}}
dict2 = {'c': 3, 'b': {'z': 30, 'y': 50}}
print(deep_merge(dict1, dict2))
{'a': 1, 'b': {'x': 10, 'y': 50, 'z': 30}, 'c': 3}

The deep_merge function recursively combines nested dictionaries while preserving their hierarchical structure. Unlike simple merging methods, it intelligently handles nested dictionary values by merging them separately instead of overwriting the entire nested structure.

  • The function creates a copy of the first dictionary to avoid modifying the original data
  • It checks if matching keys contain nested dictionaries in both sources
  • When it finds nested dictionaries, it calls itself recursively to merge those inner structures
  • For non-dictionary values or new keys, it simply updates or adds them directly

In the example, the nested dictionary under key 'b' demonstrates this behavior. The function preserves 'x' from the first dictionary while updating 'y' with the new value and adding 'z' from the second dictionary. This creates a complete merge that respects the entire data structure.

Get unstuck faster with Claude

Claude is an AI assistant created by Anthropic that excels at helping developers write, debug, and understand code. The examples above demonstrate some of Python's dictionary merging techniques. Claude can explain these concepts in depth and help you choose the right approach for your specific use case.

Working alongside you as an AI code mentor, Claude provides clear explanations and practical guidance when you encounter coding challenges. You can ask about optimizing dictionary operations, handling edge cases with nested data structures, or understanding the performance implications of different merging methods.

Start accelerating your Python development today. Sign up for free at Claude.ai to get personalized assistance with your coding questions and technical challenges.

Some real-world applications

Dictionary merging techniques power essential software features that developers use daily, from handling configuration settings to processing data from external services.

Merging default and user configurations with ** operator

The ** unpacking operator enables seamless merging of default application settings with user-provided configurations, creating a final configuration that intelligently overrides default values while preserving unspecified ones.

default_config = {'debug': False, 'log_level': 'INFO', 'max_retries': 3}
user_config = {'log_level': 'DEBUG', 'timeout': 30}
final_config = {**default_config, **user_config}
print(final_config)

This code demonstrates a practical way to handle configuration settings by combining two dictionaries. The default_config dictionary contains predefined settings with standard values. When a user provides custom settings in user_config, the ** unpacking operator merges them together.

  • The user_config values take precedence over matching keys in default_config
  • New keys from user_config (like 'timeout') get added to the final configuration
  • Unmodified default values remain intact

The resulting final_config dictionary contains all settings: overridden values from the user, new user-defined settings, and unchanged defaults. This pattern creates flexible, customizable configuration systems.

Combining data from multiple API responses

The ** unpacking operator efficiently combines user data and order information from multiple API endpoints into unified customer profiles, enabling applications to build complete views of user activity and preferences.

# Simulate responses from different API endpoints
user_data = {'id': 123, 'name': 'John Doe', 'email': 'john@example.com'}
order_data = {'order_id': 456, 'user_id': 123, 'items': 5, 'total': 99.95}

# Merge the data to create a complete user profile
user_profile = {**user_data}
if user_data['id'] == order_data['user_id']:
    user_profile['orders'] = {'count': order_data['items'], 'value': order_data['total']}

print(user_profile)

This code demonstrates how to merge user and order data from separate API responses into a unified profile. The first two dictionaries simulate API responses containing basic user information and order details. Using the ** unpacking operator, the code creates a new user_profile dictionary with the user's data.

The conditional statement checks if the user IDs match between both sources. When they do, it adds a new orders key to the profile containing a summary of the order information. This approach maintains data integrity by only combining information that belongs to the same user.

  • Creates a clean user profile without modifying original data
  • Intelligently matches records using ID verification
  • Restructures order data into a more concise format

Common errors and challenges

Python dictionary merging can trigger subtle bugs and unexpected behavior when handling key conflicts, modifying data structures, or working with nested dictionaries.

Handling key collisions when merging dictionaries

Key collisions occur when dictionaries share identical keys but contain different values. The order of merging determines which value persists in the final dictionary. Let's examine a common scenario where merging user preferences with defaults produces unexpected results.

# Trying to add default settings while preserving user preferences
user_prefs = {'theme': 'dark', 'font_size': 12}
default_prefs = {'theme': 'light', 'font_size': 10, 'notifications': True}
merged_prefs = {**user_prefs, **default_prefs}
print(merged_prefs)

The code overwrites user preferences with defaults because the ** operator applies dictionaries from left to right. default_prefs values replace the customized user_prefs settings. The following example demonstrates the correct merging order.

# Correct order: defaults first, then user preferences to override
user_prefs = {'theme': 'dark', 'font_size': 12}
default_prefs = {'theme': 'light', 'font_size': 10, 'notifications': True}
merged_prefs = {**default_prefs, **user_prefs}
print(merged_prefs)

The corrected code places default_prefs before user_prefs in the merge operation, ensuring user preferences take precedence over default settings. This ordering preserves customizations while filling in missing values from defaults.

Watch for key collisions when merging configuration dictionaries, API responses, or any data structures where value precedence matters. The rightmost dictionary in the merge operation always wins conflicts. Consider documenting your merge order conventions to prevent confusion.

  • Always merge defaults first, then custom settings
  • Test with overlapping keys to verify correct precedence
  • Document the expected behavior for your team

Avoiding unintended dictionary modifications with update()

The update() method modifies dictionaries in place rather than creating new copies. This behavior can lead to unintended side effects when you pass dictionaries as function arguments. The code below demonstrates how modifying a configuration dictionary affects both the new and original versions.

def add_settings(user_config, extra_settings):
    user_config.update(extra_settings)
    return user_config

original_config = {'debug': False, 'timeout': 30}
new_config = add_settings(original_config, {'verbose': True})
print("New config:", new_config)
print("Original config:", original_config)  # Original is modified too!

The add_settings() function directly modifies the input dictionary. When you pass original_config as an argument, Python uses the reference to update both dictionaries simultaneously. Let's examine the corrected implementation below.

def add_settings(user_config, extra_settings):
    return {**user_config, **extra_settings}

original_config = {'debug': False, 'timeout': 30}
new_config = add_settings(original_config, {'verbose': True})
print("New config:", new_config)
print("Original config:", original_config)  # Original remains unchanged

The improved code uses the ** unpacking operator to create a new dictionary instead of modifying the original one with update(). This approach preserves the input dictionary while returning a merged copy containing both the original and new settings.

  • Always create copies when modifying dictionaries in functions to prevent unintended side effects
  • Watch for functions that modify dictionaries passed as arguments
  • Consider using immutable data structures when data integrity is crucial

This pattern becomes especially important when working with configuration management, shared resources, or any scenario where multiple parts of your code reference the same dictionary. The ** operator provides a clean, reliable way to merge dictionaries without mutation risks.

Merging nested dictionaries correctly

Standard dictionary merging techniques can unexpectedly overwrite nested dictionaries instead of combining their contents. The ** operator replaces entire nested structures rather than merging them recursively. Consider this problematic scenario:

settings = {'display': {'theme': 'dark'}, 'audio': {'volume': 80}}
updates = {'display': {'font': 'Arial'}, 'audio': {'mute': False}}
merged = {**settings, **updates}
print(merged)  # Nested dictionaries are replaced, not merged

The ** operator completely overwrites nested dictionaries instead of intelligently combining their contents. When merging settings and updates, the code loses the original 'theme' and 'volume' values. Let's examine the corrected implementation below.

def deep_merge(dict1, dict2):
    result = dict1.copy()
    for key, value in dict2.items():
        if key in result and isinstance(result[key], dict) and isinstance(value, dict):
            result[key] = deep_merge(result[key], value)
        else:
            result[key] = value
    return result

settings = {'display': {'theme': 'dark'}, 'audio': {'volume': 80}}
updates = {'display': {'font': 'Arial'}, 'audio': {'mute': False}}
merged = deep_merge(settings, updates)
print(merged)

The deep_merge function recursively combines nested dictionaries by checking if matching keys contain dictionary values. When it finds nested dictionaries, it merges them separately instead of replacing the entire structure. This preserves all settings while combining new values at each level.

  • Watch for nested dictionaries in configuration files and API responses
  • Standard merging methods can silently overwrite nested data
  • Consider using deep_merge when working with complex, multi-level dictionaries that need careful preservation of all values

The recursive approach ensures no data loss when merging hierarchical structures like user preferences or application settings. Each nested dictionary gets individual attention during the merge process.

Learning or leveling up? Use Claude

Claude stands out as a sophisticated AI companion that transforms complex programming concepts into clear, actionable insights. Its deep understanding of Python and software development patterns makes it an invaluable resource for developers seeking to enhance their dictionary manipulation skills.

  • Dictionary basics: Ask "What's the difference between update() and | operator?" and Claude will explain their unique behaviors and best use cases.
  • Performance optimization: Ask "Which merging method is most memory efficient?" and Claude will analyze the memory impact of different approaches.
  • Debugging help: Ask "Why is my nested dictionary merge losing data?" and Claude will help identify common pitfalls and solutions.
  • Best practices: Ask "How should I handle key collisions in my config files?" and Claude will provide proven strategies for managing conflicting keys.

Experience personalized coding assistance today by signing up at Claude.ai.

For a more integrated development experience, Claude Code brings AI assistance directly into your terminal, enabling seamless collaboration while you write and debug Python code.

FAQs

Additional Resources

How to print in Python

2025-05-22
14 min
 read
Read more

How to subtract in Python

2025-05-30
14 min
 read
Read more

How to print a list in Python

2025-05-30
14 min
 read
Read more

Leading companies build with Claude

ReplitCognitionGithub CopilotCursorSourcegraph
Try Claude
Get API Access
Copy
Expand