Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The price of using infinite_defaultdict

This is for me a heaven sent:

>>> from collections import defaultdict
>>> infinite_defaultdict = lambda: defaultdict(infinite_defaultdict)
>>> d = infinite_defaultdict() 
>>> d['x']['y']['z'] = 10

by Raymond Hettinger on Twitter

Having that I don't see why we should do these anymore:

mydict = defaultdict(list)
mydict = defaultdict(lambda: defaultdict(float))

etc....

But I may be wrong. Is there a case where you want to avoid infinite_defaultdict?

Update: I tried to benchmark the time

from collections import defaultdict

def infdd():
   infinite_defaultdict = lambda: defaultdict(infinite_defaultdict)
   idd = infinite_defaultdict()
   idd['x'] = [1,2,3]

def plaindd():
   ddl  = defaultdict(list)
   ddl['x'] = [1,2,3]

if __name__ == '__main__':
    import timeit
    print "Infd = %.3f" % (timeit.timeit("infdd()",setup="from __main__ import infdd"))
    print "Plaind = %.3f" % (timeit.timeit("plaindd()",setup="from __main__ import plaindd"))

Apparently infinite_dict is almost twice as slow than normal:

Infd = 0.632
Paind = 0.387
like image 669
neversaint Avatar asked Nov 11 '22 10:11

neversaint


1 Answers

If you need the default value to be something other than a dict, then you should not use infinite_defaultdict. For example, if you want to count items or accumulate arrays of items, you'll want the default value to be a number or an array.

def group_by(key, items):
    result = defaultdict(list)
    for item in items:
        result[key(item)].append(item)
    return result

group_by(len, ['here', 'are', 'some', 'words'])
# -> { 3: ['are'] 4: ['here', 'some'], 5: ['words'] }
like image 101
dpercy Avatar answered Nov 14 '22 22:11

dpercy