Python defaultdict and lambda
Solution 1:
I think the first line means that when I call
x[k]
for a nonexistent keyk
(such as a statement likev=x[k]
), the key-value pair(k,0)
will be automatically added to the dictionary, as if the statementx[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
.
Solution 2:
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}}
Solution 3:
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.
Solution 4:
All answers are good enough still I am giving the answer to add more info:
"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