一线树实现
One line tree implementation
Based of this answer, I want to create a one line tree 作为另一个 class 的一部分,像这样:
self._tree = collections.defaultdict(lambda: self._tree)
我将需要允许上述 class 的用户将路径元素添加到树和 运行 从最低树级别开始的一些回调。当我 运行 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)
如果树定义为
,则此代码有效
def tree():
return collections.defaultdict(tree)
self._tree = tree()
为什么我的幼稚方法不适用于 lambda 表达式?
⚠ Zen of Python 表示
Simple is better than complex.
单行 lambda 使代码变得复杂 simpler implementation。因此,单行 lambda 不应在生产代码中使用 。但是,出于学术兴趣,我将把这个问题留在这里。
第一个 linked 问题中的单行 defaultdict 设计对我来说不合适。它会产生不寻常的自引用循环:
>>> 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...
第二个 link 中函数的单行 lambda 实现看起来更像:
tree = lambda: defaultdict(tree); self._tree = tree()
编辑:看起来你可以在一个语句中完成:
self._tree = (lambda f: f(f))(lambda t: defaultdict(lambda: t(t)))
...但是要求大学水平的 lambda 演算技能只是为了将脚本缩小一个语句似乎是不明智的交易。考虑一种更容易理解的方法。
即使使用来自 that answer 的代码,它也有完全相同的问题:
d = collections.defaultdict(lambda:d)
assert d is d[1] is d[2][4]
每个子字典只创建对自身的引用而不是新字典。
为了使其正常工作,lambda 需要创建一个新的 defaultdict
对象,并将其自身(lambda 表达式)作为第一个参数。但是,对 lambda 的唯一引用保留为 self._tree.default_factory
,因此单行代码必须如下所示:
self._tree = collections.defaultdict(lambda:collections.defaultdict(self._tree.default_factory))
这本身就很混乱,我怎么强调都不为过我建议反对在一行中这样做。
Based of this answer, I want to create a one line tree 作为另一个 class 的一部分,像这样:
self._tree = collections.defaultdict(lambda: self._tree)
我将需要允许上述 class 的用户将路径元素添加到树和 运行 从最低树级别开始的一些回调。当我 运行 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)
如果树定义为
,则此代码有效 def tree():
return collections.defaultdict(tree)
self._tree = tree()
为什么我的幼稚方法不适用于 lambda 表达式?
⚠ Zen of Python 表示
Simple is better than complex.
单行 lambda 使代码变得复杂 simpler implementation。因此,单行 lambda 不应在生产代码中使用 。但是,出于学术兴趣,我将把这个问题留在这里。
第一个 linked 问题中的单行 defaultdict 设计对我来说不合适。它会产生不寻常的自引用循环:
>>> 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...
第二个 link 中函数的单行 lambda 实现看起来更像:
tree = lambda: defaultdict(tree); self._tree = tree()
编辑:看起来你可以在一个语句中完成:
self._tree = (lambda f: f(f))(lambda t: defaultdict(lambda: t(t)))
...但是要求大学水平的 lambda 演算技能只是为了将脚本缩小一个语句似乎是不明智的交易。考虑一种更容易理解的方法。
即使使用来自 that answer 的代码,它也有完全相同的问题:
d = collections.defaultdict(lambda:d)
assert d is d[1] is d[2][4]
每个子字典只创建对自身的引用而不是新字典。
为了使其正常工作,lambda 需要创建一个新的 defaultdict
对象,并将其自身(lambda 表达式)作为第一个参数。但是,对 lambda 的唯一引用保留为 self._tree.default_factory
,因此单行代码必须如下所示:
self._tree = collections.defaultdict(lambda:collections.defaultdict(self._tree.default_factory))
这本身就很混乱,我怎么强调都不为过我建议反对在一行中这样做。