defaultdict

The defaultdict type is similar to the dict type, except it adds a default factory for new keys. This avoids the need to write an extra test to initialize the mapping entry, and is also more efficient than the dict.setdefault method.

defaultdict may seem like simple syntactic sugar over dict that allows us to write shorter code. However, the fallback to a pre-defined value on a failed key lookup is lightly faster than the dict.setdefault() method, as follows:

$ python3 -m timeit \
> -s 'd = {}' 
> 'd.setdefault("x", None)'
10000000 loops, best of 3: 0.153 usec per loop
$ python3 -m timeit \ 
> -s 'from collections import defaultdict; d=defaultdict(lambda: None)' \
> 'd["x"]'
10000000 loops, best of 3: 0.0447 usec per loop  

The difference isn't great in the preceding example because the computational complexity hasn't changed. The dict.setdefault method consists of two steps (key lookup and key set), both of which have a complexity of O(1), as we saw in the Dictionaries section in Chapter 3, Modern Syntax Elements - Below the Class Level. There is no way to have a complexity class lower than O(1), but it is indisputably faster in some situations. Every small speed improvement counts when optimizing critical code sections.

The defaultdict type takes a factory as a parameter, and can therefore be used with built-in types or classes whose constructors do not take arguments. The following code snippet is an example from the official documentation that demonstrates how to use defaultdict for counting:

>>> s = 'mississippi'
>>> d = defaultdict(int)
>>> for k in s:
...     d[k] += 1
...
>>> list(d.items())
[('i', 4), ('p', 2), ('s', 4), ('m', 1)]