Search code examples
pythonlist-comprehensiondefaultdictgenerator-expression

Populating a defaultdict at init time


How can I get a callable factory for a defaultdict to allow populating it with a comprehension? I think it's probably not possible, but I can't think of a good reason why?

>>> def foo(*args):
...     # TODO
...
>>> from collections import defaultdict
>>> thing = foo(defaultdict, int)
>>> d = thing((i, i*i) for i in range(3))
>>> d[2]
# should return 4
>>> d[-1]
# should return 0

Solution

  • Any arguments to defaultdict after the default_factory are treated just like arguments to dict:

    >>> defaultdict(int, [(i, i*i) for i in range(5)])
    defaultdict(<type 'int'>, {0: 0, 1: 1, 2: 4, 3: 9, 4: 16})
    

    Just pass the comprehension to defaultdict and let it do the work:

    def defaultdict_factory_factory(default_factory):
        def defaultdict_factory(*args, **kwargs):
            return defaultdict(default_factory, *args, **kwargs)
        return defaultdict_factory
    

    Or use functools.partial:

    def defaultdict_factory_factory(default_factory):
        return partial(defaultdict, default_factory)