Python defaultdict and lambda

Question:

In someone else’s code I read the following two lines:

``````x = defaultdict(lambda: 0)
y = defaultdict(lambda: defaultdict(lambda: 0))
``````

As the argument of defaultdict is a default factory, I think the first line means that when I call x[k] for a nonexistent key k (such as a statement like v=x[k]), the key-value pair (k,0) will be automatically added to the dictionary, as if the statement x[k]=0 is first executed. Am I correct?

And what about y? It seems that the default factory will create a defaultdict with default 0. But what does that mean concretely? I tried to play around with it in Python shell, but couldn’t figure out what it is exactly.

I think the first line means that when I call `x[k]` for a nonexistent key `k` (such as a statement like `v=x[k]`), the key-value pair `(k,0)` will be automatically added to the dictionary, as if the statement `x[k]=0` is first executed.

That’s right. This is more idiomatically written

``````x = defaultdict(int)
``````

In the case of `y`, when you do `y["ham"]["spam"]`, the key `"ham"` is inserted in `y` if it does not exist. The value associated with it becomes a `defaultdict` in which `"spam"` is automatically inserted with a value of `0`.

I.e., `y` is a kind of “two-tiered” `defaultdict`. If `"ham" not in y`, then evaluating `y["ham"]["spam"]` is like doing

``````y["ham"] = {}
y["ham"]["spam"] = 0
``````

in terms of ordinary `dict`.

`defaultdict` takes a zero-argument callable to its constructor, which is called when the key is not found, as you correctly explained.

`lambda: 0` will of course always return zero, but the preferred method to do that is `defaultdict(int)`, which will do the same thing.

As for the second part, the author would like to create a new `defaultdict(int)`, or a nested dictionary, whenever a key is not found in the top-level dictionary.

You are correct for what the first one does. As for `y`, it will create a defaultdict with default 0 when a key doesn’t exist in `y`, so you can think of this as a nested dictionary. Consider the following example:

``````y = defaultdict(lambda: defaultdict(lambda: 0))
print y['k1']['k2']   # 0
print dict(y['k1'])   # {'k2': 0}
``````

To create an equivalent nested dictionary structure without defaultdict you would need to create an inner dict for `y['k1']` and then set `y['k1']['k2']` to 0, but defaultdict does all of this behind the scenes when it encounters keys it hasn’t seen:

``````y = {}
y['k1'] = {}
y['k1']['k2'] = 0
``````

The following function may help for playing around with this on an interpreter to better your understanding:

``````def to_dict(d):
if isinstance(d, defaultdict):
return dict((k, to_dict(v)) for k, v in d.items())
return d
``````

This will return the dict equivalent of a nested defaultdict, which is a lot easier to read, for example:

``````>>> y = defaultdict(lambda: defaultdict(lambda: 0))
>>> y['a']['b'] = 5
>>> y
defaultdict(<function <lambda> at 0xb7ea93e4>, {'a': defaultdict(<function <lambda> at 0xb7ea9374>, {'b': 5})})
>>> to_dict(y)
{'a': {'b': 5}}
``````

`y = defaultdict(lambda:defaultdict(lambda:0))`

will be helpful if you try this `y['a']['b'] += 1`

“defaultdict requires an argument that is callable. That return result of that callable object is the default value that the dictionary returns when you try to access the dictionary with a key that does not exist.”

Here’s an example

``````SAMPLE= {'Age':28, 'Salary':2000}
SAMPLE = defaultdict(lambda:0,SAMPLE)

>>> SAMPLE
defaultdict(<function <lambda> at 0x0000000002BF7C88>, {'Salary': 2000, 'Age': 28})

>>> SAMPLE['Age']----> This will return 28
>>> SAMPLE['Phone']----> This will return 0   # you got 0 as output for a non existing key inside SAMPLE
``````
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.