惯用Python:传播yield还是扁平化序列?
我正在写一个深度优先遍历树的函数,我想要实现的是这个:
def traverse(node):
yield node
for n in node.children:
yield_all traverse(n) # << if Python had a yield_all statement
我的目标是得到树中节点的一个(扁平化的)序列。
方法一:(传播生成)
def traverse(node):
yield node
for n in node.children:
for m in traverse(n):
yield m
方法二:(扁平化序列)
def traverse(node):
return itertools.chain([node],*(traverse(n) for n in node.children))
第一种方法看起来更干净,但我觉得在每一层的子树中明确地yield
每个节点有点奇怪。
第二种方法简洁但稍微有点乱,不过它和我在Haskell中写的代码很像:
traverse node = node : concatMap traverse (children node)
所以我的问题是:哪种方法更好?或者我是不是漏掉了更好的第三种选择?
4 个回答
1
这个问题是个意见类的问题,所以所有的回答都是个人看法。就我所想,似乎没有什么优雅的第三种选择。
我个人认为第一种方法绝对是最好的。它更清晰,也更容易阅读——Python 不是 Haskell,虽然它可以做一些函数式编程的事情,但通常函数式的方法看起来就是不那么整洁。
3
我建议选择第一个。你过几次就会习惯传递收益了。:-)
5
[更新] 请查看 PEP-380,这个 yield all 语法从 Python 3.3 开始可以使用,写法是 yield from
:
def traverse(node):
yield node
for n in node.children:
yield from traverse(n)