Autovivification in Python: nested defaultdicts with a specific final type
Saturday, May 26th, 2012I quite often miss the flexibility of autovivification in Python. That Wikipedia link shows a cute way to get what Perl has:
def tree():
return defaultdict(tree)
lupin = tree()
lupin["express"][3] = "stand and deliver"
It’s interesting to think about what’s going on in the above code and why it works. I really like defaultdict.
What I more often want, though, is not infinitely deep nested dictionaries like the above, but a (known) finite number of nested defaultdicts with a specific type at the final level. Here’s a tiny function I wrote to get just that:
def autovivify(levels=1, final=dict):
return (defaultdict(final) if levels < 2 else
defaultdict(lambda: autovivify(levels – 1, final)))
So let’s say you were counting the number of occurrences of words said by people by year, month, and day in a chat room. You’d write:
words["sam"][2012][5][25]["hello"] += 1
words["sue"][2012][5][24]["today"] += 1
Etc. It’s pretty trivial, but it was fun to think about how to do it with a function and to play with some alternatives. You could do it manually with nested lambdas:
words["sam"]["hello"] += 1
But that gets messy quickly and isn’t nearly as much fun.