惯用Python:传播产量还是扁平化序列?

惯用Python:传播产量还是扁平化序列?,python,yield,tree-traversal,Python,Yield,Tree Traversal,我正在编写一个广度-深度优先树遍历函数,我想做的是: def traverse(node): yield node for n in node.children: yield_all traverse(n) # << if Python had a yield_all statement 方法2:(展平序列) 第一种方法看起来更干净,但我觉得奇怪的是,在每一级显式地yielding子树中的每个节点 第二种方法简洁且略显肮脏,但它与我在Haskell中

我正在编写一个广度-深度优先树遍历函数,我想做的是:

def traverse(node):
    yield node
    for n in node.children:
        yield_all traverse(n) # << if Python had a yield_all statement
方法2:(展平序列)

第一种方法看起来更干净,但我觉得奇怪的是,在每一级显式地
yield
ing子树中的每个节点

第二种方法简洁且略显肮脏,但它与我在Haskell中所写的内容相匹配:

traverse node = node : concatMap traverse (children node)

所以我的问题是:哪一个更好?还是我缺少了最好的第三个选项?

[UPDATE]请参见,此生成所有语法都可以从as
开始生成:

def traverse(node):
    yield node
    for n in node.children:
        yield from traverse(n)

我会先去。几次之后,您将克服繁殖产量的问题。:-)

这是一个观点问题,所以所有的答案都是价值判断。但就我所知,没有优雅的第三条路


我的意见是,第一种方式可以轻而易举地获胜。它更清晰、更容易阅读——Python不是Haskell,尽管它可以做一些功能性的东西,而且通常功能性方法看起来并不整洁。

使用节点位置遍历:

def iter_tree(t, i=0, j=0):
    yield (i, j), t
    for j, n in enumerate(t.children):
        yield from iter_tree(n, i + 1, j)

for (i, j), n in iter_tree(t):
    print(i*'    ', (i, j), n)

罗列理解会让这更清楚。雷夫:写一个答案,让我看看!:-)我想看一份这方面的理解清单。。。最后你需要把它压平,对吗?就我而言,
解决方案非常好。方法2不起作用。您将得到
TypeError:type对象参数*后面必须是序列,而不是生成器。
。这不是树的深度优先遍历吗?你不是在要求广度优先吗?啊,有时候我希望Python能做的一切似乎都埋在某个地方的PEP里了。我应该开始收集pep模块,或者只是学习接受Python不是真正的函数式语言。@perimosocordiae:了解GvR对FP的看法,我在这个角度上不会有太多期望。但是如果没有Kuchling和Hettinger(以及其他人)与FP相关的工作,Python肯定会是一种更悲哀的语言。
def traverse(node):
    yield node
    for n in node.children:
        yield from traverse(n)
def iter_tree(t, i=0, j=0):
    yield (i, j), t
    for j, n in enumerate(t.children):
        yield from iter_tree(n, i + 1, j)

for (i, j), n in iter_tree(t):
    print(i*'    ', (i, j), n)