5 ms·
c = defaultdict(lambda: 42) b = defaultdict(lambda: c) a = defaultdict(lambda: b) a["a"]["b"]["c"] # --> 42
by kotlin2 4y ago
c = defaultdict(lambda: 42)
b = defaultdict(lambda: c)
a = defaultdict(lambda: b)
a["a"]["b"]["c"] # --> 42
- Spivak 4y agoOkay fair, I deserve that. I assumed it was obvious I meant arbitrary depth. Also d["a"] and d["a"]["b"] aren't 42.
- kotlin2 4y agoIf d["a"]["b"] is 42, then how could d["a"]["b"]["c"] also be 42? What you want doesn't make sense semantically. Normally, we'd expect these two statements to be equivalent d["a"]["b"]["c"] == (d["a"]["b"])["c"]
- Spivak 4y agoI mean you got it but it's something a lot of people want. The semantic reason for it is so you can look up an arbitrary path on a dict and if it's not present get a default, usually None. It can be done by catching KeyError but it has to happen on the caller side which is annoying. I can't make a real nested mapping that returns none if the keys aren't there. d = magicdict() is42 = d["foo"]["bar"]["baz"] # -> You can read any path and get a default if it doesn't exist. d["hello"]["world"] = 420 # -> You can set any path and d will then contain { "hello": { "world": 420 } People use things like jmespath to do this but the fundamental issue is that __getitem__ isn't None safe when you want nested dicts. It's a godsend when dealing with JSON. I feel like we're maybe too in the weeds, I should have just said "now have two expressions in your lambda."
- kotlin2 4y agoWhat languages allow such a construct? It seems like it would be super confusing if these two code samples produced different values: # One a = d["a"]["b"]["c"] # Two a = d["a"]["b"] b = a["c"]
- Too 4y agoThe MagicMock class from unittest package does what you want. I have a hard time understanding any use case outside of such mocking.