我正在编写广度深度优先树遍历函数,我想要做的是:
def traverse(node):
yield node
for n in node.children:
yield_all traverse(n) # << if Python had a yield_all statement
这个想法是在树中结束一个(平坦的)节点序列。
方法#1 :(传播产量)
def traverse(node):
yield node
for n in node.children:
for m in traverse(n):
yield m
方法#2 :(展平序列)
def traverse(node):
return itertools.chain([node],*(traverse(n) for n in node.children))
第一种方法看起来更干净,但我觉得在每个级别的子树中明确yield
每个节点都很奇怪。
第二种方法简洁而略显肮脏,但它与我在Haskell中编写的内容相符:
traverse node = node : concatMap traverse (children node)
所以我的问题是:哪个更好?或者我错过了最好的第三选择?
答案 0 :(得分:4)
[更新] 请参阅PEP-380,此全部语法可从Python 3.3开始作为yield from
:
def traverse(node):
yield node
for n in node.children:
yield from traverse(n)
答案 1 :(得分:3)
我先去。几次后你就会克服收益率。 : - )
答案 2 :(得分:1)
这是一个意见问题,因此所有答案都只是价值判断。据我所知,没有优雅的第三种方式。
我的观点是第一种方式胜出手。它更清晰,更容易阅读 - 虽然Python可以做一些功能性的东西,但它不是Haskell,而且功能方法通常看起来不那么整洁。
答案 3 :(得分:0)
遍历节点位置:
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)