Based of this answer, I want to create a one line tree as part of another class like thus:
self._tree = collections.defaultdict(lambda: self._tree)
I will need to allow the users of said class to add path elements to the tree and run some callback starting at the lowest tree level. My naive implementation raises a error when I run pytest
:
def _add(self, tree, path):
for node in path:
tree = tree[node]
def _run(self, tree, callback):
for key in tree.keys():
callback(tree[key]) # !!! Recursion detected (same locals & position)
self._run(key)
This code works iff the tree is defined as
def tree():
return collections.defaultdict(tree)
self._tree = tree()
Why is my naive approach not working with the lambda expression?
⚠ The Zen of Python states that
Simple is better than complex.
The one-line lambda makes the code complex where there is a simpler implementation. Therefore the one-line lambda should not be used in production code. However, I shall leave this question here for academic interest.
The one-line defaultdict design in the first linked question doesn't look right to me. It produces unusual self-referential loops:
>>> d = collections.defaultdict(lambda: d)
>>> d["a"] = 23
>>> d["b"]["c"] = 42
>>> print d["b"]["a"] #we never created a value with these keys, so it should just return a defaultdict instance.
23
>>> #uh, that's not right...
A one-line lambda implementation of the function in your second link would look more like:
tree = lambda: defaultdict(tree); self._tree = tree()
Edit: looks like you can do it in a single statement with:
self._tree = (lambda f: f(f))(lambda t: defaultdict(lambda: t(t)))
... But requiring college-level lambda calculus skills just to shrink your script by one statement seems like an unwise bargain. Consider a more understandable approach.