1

I came across this code from https://quanttype.net/posts/2016-03-29-defaultdicts-all-the-way-down.html and I am not able to understand how or why this is working. I would love to know how someone could visualize this and understand this

Running this inside a debugger did not yield an understanding

def fix(f):
    return lambda *args, **kwargs: f(fix(f), *args, **kwargs)

>>> from collections import defaultdict
>>> d = fix(defaultdict)()
>>> d["a"]["b"]["c"]
defaultdict(<function <lambda> at 0x105c4bed8>, {})
  • 2
    Did you try reading the documentation for `defaultdict`? – Karl Knechtel Oct 31 '19 at 00:57
  • Yes, I read it multiple times. This should be the relevant part "The first argument provides the initial value for the default_factory attribute; it defaults to None. All remaining arguments are treated the same as if they were passed to the dict constructor, including keyword arguments." but it does not aid my understanding. – Vikash Raja Samuel Selvin Oct 31 '19 at 01:05
  • See also https://stackoverflow.com/questions/5900578/how-does-collections-defaultdict-work – Karl Knechtel Oct 31 '19 at 01:08

1 Answers1

0

Let's consider a slightly simpler version of fix:

def fix(f):
    return lambda: f(fix(f))

When we call fix(defaultdict), we of course get lambda: defaultdict(fix(defaultdict)). It will return a separate lambda each time, but all of those lambda functions have the same net effect. When the first lambda is called, it creates another one, and sets that as the factory for the defaultdict that it returns.

The defaultdict that we get back, will use the lambda to create default values. So when a key-value pair is inserted, the value will become another defaultdict, that has its own lambda, which can do the same thing.

This lets us store keys as deep as we want without creating the sub-dicts first, because at each level the new layer will automatically be created if needed (and that layer is set up to create the next when needed, and so on).

The fix in the actual code just forwards additional parameters to the defaultdict constructor. The sample code doesn't use that functionality, but it could be used to initialize the contents instead of assigning them one at a time (see the documentation for defaultdict for more details).

Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153