50

I try to sum two dictionaries like that:

my_new_dict = dict(my_existing_dict.items() + my_new_dict.items())

but recieve error

TypeError: unsupported operand type(s) for +: 'dict_items' and 'dict_items'

What I do wrong?

1
  • Sidenote: If you want to iterate over two dictionaries, and you know they have unique keys (or it doesn't matter if you process the same key twice), consider using itertools.chain(dict_a, dict_b)
    – Moberg
    Commented Dec 7, 2016 at 7:57

4 Answers 4

76

As of Python 3.9 (PEP 584 in particular), dicts gains union (|) and update (|=) operations just like sets, so that becomes the "one true way" to achieve what you are looking for.

d3 = d1 | d2

With the second dictionary taking precedence in the case of key collision.

That PEP lists the other options available in earlier Python versions, which all have their downsides. If you are up to PEP 448 (Python 3.5), I would recommend using:

{**d1, **d2}

This is unpacking both dictionaries into a new one, resulting in a union.

One problem is the behavior you want is ambiguous - dictionaries can't have duplicate keys, so it is unclear what you want to happen if both contain the same key. The spec is explicit about what should happen when using this method:

In dictionaries, later values will always override earlier ones

If you want the reverse behaviour, you can simply swap the order of the dictionaries in the literal.

Your approach doesn't work because dictionary views are set-like, so they don't have addition implemented.

What you probably want is the union: d1.items() | d2.items(), which will give you a set of tuples of (key, value). If you then pass it to dict() and there are duplicates, the "last" value will be the one used, however sets (unlike the views themselves) are unordered, so there is no guarantee about which item will end up "first" in the combined set, meaning that which one "wins" will be arbitrary.

So, in short, as long as order/duplicate selection isn't important:

dict(d1.items() | d2.items())

In Python 2, dict.items() simply returns a list, where your approach will work.

7
  • 8
    When I try this I get: TypeError: unhashable type: 'dict'
    – Greg K
    Commented Dec 25, 2014 at 5:06
  • With Python 3.6.1, I noticed if an item is in both d1 and d2, it seems dict(d1.items() | d2.items()) results in d1's items taking effect in case of duplicates, which is not what I expected. dict(list(d1.items()) + list(d2.items())) behaves as I expect, with d2 winning in case of duplicates.
    – erwaman
    Commented Nov 19, 2018 at 14:18
  • @erwaman Yes, sets are unordered, while dictionaries are (now) ordered. My wording was misleading because "last" doesn't mean much when sets are ordered arbitrarily. If you want to preserve order, you indeed need to use an ordered collection like a list (at a small additional cost of constructing them). Commented Nov 19, 2018 at 14:28
  • @erwaman See my latest edit for an updated approach I think is the best option in all cases. Commented Nov 19, 2018 at 14:39
  • Maybe you can also opt for: {**dict(item for item in original_dict.items() if item[0] not in updating_dict),**updating_dict}
    – eliax1996
    Commented Oct 30, 2023 at 16:59
31

In python3, dict.items() returns an object with type dict_items which apparently can't be added. (in python 2, it returned a list which could be added).

An alternative way to add a pair of dictionaries which works on py2k and py3k:

d = dict1.copy()
d.update(dict2)

Of course, there's some ambiguity about what you want to happen in the case of key collisions. e.g. if both dicts have key1, whose key1 should be preserved in the output? Or should you use some combination of both of their values? In the latter case, you'll probably want something from the collections module (either defaultdict or Counter)

2
  • @mgilson: I think that dict.items() in 3+ is equivalent to dict.iteritems() in 2.6, that is, it's an iterator.
    – Pierre GM
    Commented Nov 13, 2012 at 13:43
  • @PierreGM No, it returns a dictionary view, which is a set-like container (see my answer). Commented Nov 13, 2012 at 13:44
15

Another approach to the other suggested answers is:

dict(list(d1.items()) + list(d2.items()))

If there are keys present in both d1 and d2, the value in d2 will be used in the final dictionary.

1
  • 1
    Must be new, doesn't work in 3.5.2 but works in 3.6.9. Wish they would just add the common sense syntax of dictN.items() + dictN.items()...
    – Ian Smith
    Commented Dec 31, 2019 at 5:40
0

I'm surprised nobody has mentioned ChainMap.

from collections import ChainMap

dict1 = {'a': 1, 'b': 2}
dict2 = {'c': 3, 'd': 4}

combined = ChainMap(dict1, dict2)

print(combined['a']) # Output: 1
print(combined['c']) # Output: 3

From the documentation:

It is often much faster than creating a new dictionary and running multiple update() calls.

It will also preserve order if that's important.

Not the answer you're looking for? Browse other questions tagged or ask your own question.