Python生成器:正确的代码递归树

Geo*_*rge 8 python recursion generator

class Node(object):
    def __init__(self, lst):
        if type(lst) == list:
            self.value = lst[0]
            self.children = lst[1:]
        else:
            self.value = lst
            self.children = []
    @property
    def ChildElements(self):
        return [Node(a) for a in self.children]

    @property
    def GetValue(self):
        return self.value

def node_recurse_generator(node):
    yield node.value
    for n in node.ChildElements:
        node_recurse_generator(n)
Run Code Online (Sandbox Code Playgroud)

Node是一个简单的树状数据结构.列表的第一个元素始终是Node的值,其他元素将是子元素.如果使用除列表之外的其他内容启动节点,则该值将为该值,并且子节点将为[],空列表.

a = Node([1,[10,20,30],[100,200,300]])
>>> list(node_recurse_generator(a))
[1]
Run Code Online (Sandbox Code Playgroud)

现在,在所有元素上都有一个递归迭代器会很棒,但是我的生成器只产生第一个元素.为什么会这样?

NPE*_*NPE 15

简单地node_recurse_generator递归调用是不够的 - 你必须得到yield它的结果:

def node_recurse_generator(node):
    yield node.value
    for n in node.ChildElements:
        for rn in node_recurse_generator(n):
            yield rn
Run Code Online (Sandbox Code Playgroud)

  • 作为旁注,这就是`yield from`表达式(包含在Python 3.3中)将有助于实现.参见PEP 380:http://www.python.org/dev/peps/pep-0380/ (3认同)

Zhe*_* He 8

正如yak在顶级答案的评论中提到的,您也可以yield from在Python 3.3之后使用。

def node_recurse_generator(node):
    yield node.value
    for n in node.ChildElements:
        yield from node_recurse_generator(n)
Run Code Online (Sandbox Code Playgroud)