Difference between defaultdict(lambda:None) and defaultdict(int)

rva picture rva · Nov 22, 2015 · Viewed 8k times · Source

What exactly does the TYPE lambda do when used with defaultdict? I have this example and works fine even for int, list & lambda as argument:

d = defaultdict(int)
d['one'] = lambda x:x*x
d['one'](2)
4

d = defaultdict(list)
d['one'] = lambda x:x*x
d['one'](2)
4

d = defaultdict(lambda: None)
d['one'] = lambda x:x*x
d['one'](2)
4

I have the same result each time. So what is the main reason to initialize with lambda "default (lambda: None)"? Looks defaultdict dictionary does not care about the what TYPE of argument is passed in.

Answer

poke picture poke · Nov 22, 2015

Your example only makes sense when you access keys that are not explicitly added to the dictionary:

>>> d = defaultdict(int)
>>> d['one']
0
>>> d = defaultdict(list)
>>> d['one']
[]
>>> d = defaultdict(lambda: None)
>>> d['one'] is None
True

As you can see, using a default dict will give every key you try to access a default value. That default value is taken by calling the function you pass to the constructor. So passing int will set int() as the default value (which is 0); passing list will set list() as the default value (which is an empty list []); and passing lambda: None will set (lambda: None)() as the default value (which is None).

That’s what the default dictionary does. Nothing else.

The idea is that this way, you can set up defaults which you don’t need to manually set up the first time you want to access the key. So for example something like this:

d = {}
for item in some_source_for_items:
    if item['key'] not in d:
        d[item['key']] = []

    d[item['key']].append(item)

which just sets up a new empty list for every dictionary item when it is accessed, can be reduced to just this:

d = defaultdict(list)
for item in some_source_for_items:
    d[item['key']].append(item)

And the defaultdict will make sure to initialize the list correctly.