5

The following code uses the {} operator to combine two defaultdicts.

from collections import defaultdict
aa=defaultdict(str)
bb=defaultdict(str)
aa['foo']+= '1'
bb['bar']+= '2'
cc = {**aa,**bb}
type(cc)

But, as we see if we run this, the {} operator returns a dict type not a defaultdict type.

Is there a way to cast a dict back to a defaultdict?

jpp
  • 159,742
  • 34
  • 281
  • 339
Ray Salemi
  • 5,247
  • 4
  • 30
  • 63

3 Answers3

4

You can use unpacking directly in a call to defaultdict. defaultdict is a subclass of dict, and will pass those arguments to its parent to create a dictionary as though they had been passed to dict.

cc = defaultdict(str, **aa, **bb)
# defaultdict(<class 'str'>, {'bar': '2', 'foo': '1'})
Laurent H.
  • 6,316
  • 1
  • 18
  • 40
Patrick Haugh
  • 59,226
  • 13
  • 88
  • 96
  • This nails it. Thanks! – Ray Salemi Aug 09 '18 at 14:26
  • This is the best one-line solution. But note that unpacking makes it inefficient and inputs are over-specified, i.e. requires an input [`defaultdict` type] which shouldn't be necessary. – jpp Aug 09 '18 at 15:27
2

You can do it the long way. The benefit of this method is you don't need to re-specify the type of defaultdict:

def merge_two_dicts(x, y):
    z = x.copy()
    z.update(y)
    return z

cc = merge_two_dicts(aa, bb)

Unpacking in a single expression works but is inefficient:

n = 500000

d1 = defaultdict(int)
d1.update({i: i for i in range(n)})
d2 = defaultdict(int)
d2.update({i+n:i+n for i in range(n)})

%timeit defaultdict(int, {**d1, **d2})  # 150 ms per loop
%timeit merge_two_dicts(d1, d2)         # 90.9 ms per loop
jpp
  • 159,742
  • 34
  • 281
  • 339
0

The defaultdict constructor can take two arguments, where the first is the function to use for the default, and the second a mapping (dict). It copies the keys/values from the dict passed in.

 >>> d = defaultdict(list, {'a': [1,2,3]})
 >>> d['a']
 [1, 2, 3]
Edward Minnix
  • 2,889
  • 1
  • 13
  • 26