如何使用 python 生成器递归生成对象?

How to yield objects recursively using python generator?

我正在编写一个生成器函数,它递归地遍历给定星形节点的所有子节点。

在下面的示例中,node 是一个星形 functiondef 节点。 node.getchildren() returns 节点中有子节点的生成器。

我的目标是生成包含的每个节点。 (即使在子节点中)

def recursive_walk(node):
    try:
        for subnode in list(node.get_children()):
            # yield subnode
            print(subnode)
            recursive_walk(subnode)            

    except AttributeError:
        # yield node       
        print(node)

    except TypeError:
        # yield node  
        print(node)

这里如果我把yield语句注释掉了。 对于 print 语句,我得到了我想要的结果,但是如果我放弃了节点,我就没有得到想要的输出。

为了重现这个: - 安装 astroid

import astroid

node = astroid.extract_node('''
def test_function(something): #@
    """Test function for getting subnodes"""
    assign_line = "String"
    ctx = len(assign_line)
    if ctx > 0:
        if ctx == 1:
            return 1
        if ctx > 10:
            return "Ten"
    else:
        return 0
''')

您可以递归 map 子函数并使用 yield from:

def recursive_walk(node):
    # yield the base node
    yield node
    # for each of the recursive calls yield the remaining ones
    yield from map(recursive_walk, node.get_children())

万一他们没有 children 它什么也不会产生并继续下一个。

def recursive_walk(node):
    """
    Generator function to recursively walk through a given node.

    Yields every astroid node inside.
    """
    try:
        for subnode in node.get_children():
            yield subnode
            yield from recursive_walk(subnode)

    except (AttributeError, TypeError):
        yield node

这样就可以了。