简体   繁体   中英

reduce not working for collections.defaultdict?

Why is reduce() is not working with a defaultdict object in the following case:

>>> from collections import defaultdict
>>> d = defaultdict(lambda: defaultdict(int))
>>> reduce(dict.get, [1,2], d)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: descriptor 'get' requires a 'dict' object but received a 'NoneType'

The above reduce is equivalent to d[1][2] , so I expected 0 , ie the default return value as output but I got a NoneType exception instead.

If I use d[1][2] it works fine as shown below:

>>> d[1][2]
0

Am I doing anything wrong?

dict.get() returns None if a key is not present, even for a defaultdict object .

That's because the job of dict.get() is to return a default value instead when a key is missing. If it didn't you'd never be able to return a different default (the second argument to dict.get() ):

>>> from collections import defaultdict
>>> d = defaultdict(lambda: defaultdict(int))
>>> d.get(1, 'default')
'default'

In other words, your reduce(dict.get, ..) function is not the equivalent of the d[1][2] expression. It is the equivalent of d.get(1).get(2) , which fails the exact same way:

>>> d = defaultdict(lambda: defaultdict(int))
>>> d.get(1).get(2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'get'

Use dict.__getitem__ instead if you want to rely on the auto-insertion behaviour:

>>> reduce(dict.__getitem__, [1,2], d)
0

The expression d[1] translates directly to d.__getitem__(1) .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM