How to Merge Two Dictionaries in Python: Comprehensions, Unpacking, and the Union Operator

How to Merge Two Dictionaries in Python Featured Image

When I’m trying to find a topic for this series, I either decide to write about something I just learned, or I choose to write about something I found from the list of top Python questions on Stack OverflowOpens in a new tab.. Today, I’m hitting both by covering how to merge two dictionaries in Python.

As it turns out, there are a ton of ways to merge dictionaries. Perhaps the most common way is to make use of the update() method which allows values from one dictionary to be loaded into another dictionary: d1.update(d2). Alternatively, there’s dictionary unpacking in Python 3.5: d3 = {**d1, **d2}. In Python 3.9, there’s the union operator: d3 = d1 | d2.

In the remainder of this article, we’ll take a look at these options in more detail.

Table of Contents

Problem Introduction

Earlier in this series, I covered a similar problem where I wanted to convert two lists into a dictionary. In that article, I covered various methods for mapping one list onto the other. This time around I want to convert two dictionaries into a single dictionary like so:

yusuke_power = {"Yusuke Urameshi": "Spirit Gun"}
hiei_power = {"Hiei": "Jagan Eye"}

# Insert merge code here

powers = {
  "Yusuke Urameshi": "Spirit Gun",
  "Hiei": "Jagan Eye"
}

Here, we have two dictionaries: yusuke_power and hiei_power. Each dictionary maps a YuYu Hakasho character to one of their abilities. In this case, I chose Yusuke and his Spirit Gun as well as Hiei and his Jagan Eye. Ultimately, we want to be able to merge these dictionaries, so we have a collection of characters and their powers. Let’s see if we can accomplish that below.

Solutions

As always, I like to list off a few possible ways to solve the problem. To start, we’ll try a brute force solution, then we’ll dig into some more sophisticated solutions.

Merge Two Dictionaries with Brute Force

As is tradition in this series, I always like to kick things off with a roll-your-own solution. In this case, we’re looking to iterate over one dictionary and add its items to the other dictionary:

yusuke_power = {"Yusuke Urameshi": "Spirit Gun"}
hiei_power = {"Hiei": "Jagan Eye"}

for key, value in hiei_power.items():
  yusuke_power[key] = value

Naturally, this solution leaves a lot to be desired, but it gets the job done. At the end of the day, yusuke_power should look like the powers dictionary we want.

To accomplish something closer to what we want, we would have to iterate over both dictionaries separately:

yusuke_power = {"Yusuke Urameshi": "Spirit Gun"}
hiei_power = {"Hiei": "Jagan Eye"}
powers = dict()

for dictionary in (yusuke_power, hiei_power):
  for key, value in dictionary.items():
    powers[key] = value

Unfortunately, this solution doesn’t scale very well. That said, there are better ways to solve this problem.

Merge Two Dictionaries with a Dictionary Comprehension

Since I’m a big fan of comprehensions, I think it’s worth mentioning that the solution above can be written in a single line with a dictionary comprehension:

yusuke_power = {"Yusuke Urameshi": "Spirit Gun"}
hiei_power = {"Hiei": "Jagan Eye"}

powers = {key: value for d in (yusuke_power, hiei_power) for key, value in d.items()}

Here, we have written a dictionary comprehension that iterates over both dictionaries and copies each item into a new dictionary. Naturally, it works just like the brute force solution.

Merge Two Dictionaries with Copy and Update

As with many of the collections in Python, they have a builtin copy function associated with them. As a result, we can leverage that copy function to generate a new dictionary which includes all the items of the original dictionary. In addition, dictionaries have an update function which can be used to add all the items from one dictionary into another:

yusuke_power = {"Yusuke Urameshi": "Spirit Gun"}
hiei_power = {"Hiei": "Jagan Eye"}

powers = yusuke_power.copy()
powers.update(hiei_power)

With this solution, we’re able to generate that powers dictionary which contains all the items from the original two dictionaries. As an added benefit, copy() and update() are backwards compatible, so Python 2 users won’t feel left out.

It’s worth noting that we can extend this solution to merge any number of dictionaries with a custom function:

def merge_dicts(*dicts: dict):
  merged_dict = dict()
  for dictionary in dicts:
    merge_dict.update(dictionary)
  return merged_dict

Now, we can generate a new dictionary which contains all the items in any number of dictionaries.

Merge Two Dictionaries with Dictionary Unpacking

When Python 3.5 rolled out, it introduced a dictionary unpacking syntax which allows us to merge dictionaries with a new operator:

yusuke_power = {"Yusuke Urameshi": "Spirit Gun"}
hiei_power = {"Hiei": "Jagan Eye"}

powers = {**yusuke_power, **hiei_power}

Naturally, this solution scales for any number of arguments:

yusuke_power = {"Yusuke Urameshi": "Spirit Gun"}
hiei_power = {"Hiei": "Jagan Eye"}

powers = {**yusuke_power, **hiei_power, "Yoko Kurama": "Rose Whip"}

Of course, the drawback is backwards compatibility. If you’re still rocking Python 2 or even older versions of Python 3, this feature may not be available to you. Regardless, I think it’s a pretty clever piece of syntax, and I like how it looks.

Merging Two Dictionaries with the Union Operator

As of Python 3.9, we have access to the union operator. Basically, this allows a user to merge dicts as follows:

yusuke_power = {"Yusuke Urameshi": "Spirit Gun"}
hiei_power = {"Hiei": "Jagan Eye"}

powers = yusuke_power | hiei_power

Now, that’s slick! Like most of the solutions, this solution gives precedence to the last dictionary in the series. In this example, if both dictionaries had the same key, the value from hiei_power will be stored.

Alternatively, we could make use of the augmented assignment operator which allows us to update an existing dictionary:

yusuke_power = {"Yusuke Urameshi": "Spirit Gun"}
hiei_power = {"Hiei": "Jagan Eye"}
powers = {}

powers |= yusuke_power
powers |= hiei_power

Naturally, this works just like our update() solution. This solution is a bit more ideal for merging a large number of dictionaries as there isn’t a new dictionary being created.

Here’s the PEP 584 documentationOpens in a new tab. if you’re interested in reading more about this feature. Also, if you’re interested in my take on new operators, I’ve written a bit about the new Walrus operator in 3.8. I imagine my assessment of this operator is largely the same.

Performance

For the first time in this series, I thought it would be beneficial to take a look at the performance of each of the methods above (if you’re lucky, I might update the old articles to include performance as well). To do that, I’m going to use the builtin timeit library.

To use the timeit library, we have to set up some strings for testing:

setup = """
yusuke_power = {"Yusuke Urameshi": "Spirit Gun"};
hiei_power = {"Hiei": "Jagan Eye"};
powers = dict()
"""

brute_force = """
for dictionary in (yusuke_power, hiei_power):
  for key, value in dictionary.items():
    powers[key] = value
"""

dict_comprehension = """
powers = {key: value for d in (yusuke_power, hiei_power) for key, value in d.items()}
"""

copy_and_update = """
powers = yusuke_power.copy()
powers.update(hiei_power)
"""

dict_unpacking = """
powers = {**yusuke_power, **hiei_power}
"""

union_operator = """
powers = yusuke_power | hiei_power
"""

With our strings setup, we can begin our performance test:

>>> import timeit
>>> min(timeit.repeat(stmt=brute_force, setup=setup))
0.2620210000000043
>>> min(timeit.repeat(stmt=dict_comprehension, setup=setup))
0.3916270999999938
>>> min(timeit.repeat(stmt=copy_and_update, setup=setup))
0.12005750000000148
>>> min(timeit.repeat(stmt=dict_unpacking, setup=setup))
0.07124989999999798
>>> min(timeit.repeat(stmt=union_operator, setup=setup))
0.06799530000000686

As it turns out, dictionary unpacking and the new union operator are very fast. That’s one thing I always love about these new features: the development team always takes great care to make specialized features highly performant.

For reference, I performed the testing on a Desktop with Windows 10 and Python 3.9.0a6. If you’d like to learn more about this testing procedure, I wrote an article that outlines the whole process.

Challenge

At long last, this article finally features a challenge! Luckily, this challenge is pretty straightforward.

At this point, we’ve looked at merging a pair of dictionaries. How would we go about merging any number of dictionaries? For example, if I provided the following method signature, could you fill out the method body?

def merge_dicts(*dicts: dict) -> dict:
  pass # fill this out

I realized there’s already a solution in the update/copy section, but I figured there might be some other ways. When you have your solution, feel free to share it on Twitter using the hashtag #RenegadePythonOpens in a new tab..

In the meantime, here’s yet another solution which leverages the upcoming union operator:

Now, that’s pretty cool!

A Little Recap

Well, that’s all I have in terms of typical solutions. All that said, be aware that all of these solutions will overwrite duplicate values. In other words, if two dictionaries contain the same key, the last dictionary to be merged will overwrite the previous dictionary’s value.

Also, it’s worth noting that all of these solutions perform a shallow copy of the dictionaries. As a result, dictionaries that may be nested or store objects will only have their references copied, not the actual values. If that’s a constraint in your application, you may need to write your own recursive copy function.

At any rate, here are all the solutions:

yusuke_power = {"Yusuke Urameshi": "Spirit Gun"}
hiei_power = {"Hiei": "Jagan Eye"}
powers = dict()

# Brute force
for dictionary in (yusuke_power, hiei_power):
  for key, value in dictionary.items():
    powers[key] = value

# Dictionary Comprehension
powers = {key: value for d in (yusuke_power, hiei_power) for key, value in d.items()}

# Copy and update
powers = yusuke_power.copy()
powers.update(hiei_power)

# Dictionary unpacking (Python 3.5+)
powers = {**yusuke_power, **hiei_power}

# Backwards compatible function for any number of dicts
def merge_dicts(*dicts: dict):
  merged_dict = dict()
  for dictionary in dicts:
    merge_dict.update(dictionary)
  return merged_dict

# Union operator (Python 3.9+)
powers = yusuke_power | hiei_power

And, that’s it! As always, I appreciate the support. If you liked this article, do me a favor and share it with someone. For those feeling extra generous, consider becoming a member of The Renegade Coder. If you’re not convinced, check out some of these other Python articles:

Once again, thanks for the support! Before you go, share your recommendation for a topic you’d like to see in the comments.

Series Navigation← How to Write a List Comprehension in Python: Modifying and FilteringHow to Format a String in Python: Interpolation, Concatenation, and More →

Jeremy Grifski

Jeremy grew up in a small town where he enjoyed playing soccer and video games, practicing taekwondo, and trading Pokémon cards. Once out of the nest, he pursued a Bachelors in Computer Engineering with a minor in Game Design. After college, he spent about two years writing software for a major engineering company. Today, he pursues a PhD in Engineering Education in order to ultimately land a teaching gig. In his spare time, Jeremy enjoys spending time with his wife, playing Overwatch and Phantasy Star Online 2, practicing trombone, watching Penguins hockey, and traveling the world.

Recent Content