2

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

在下面的示例中,node是一个 astroidfunctiondef节点。 node.getchildren()返回节点中包含子节点的生成器。

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

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 语句。对于打印语句,我得到了我想要的结果,但是如果我产生节点,我没有得到想要的输出。

为了重现这个: - 安装 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
''')
4

2 回答 2

2
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

这完成了工作。

于 2019-06-04T10:03:45.470 回答
1

您可以将函数递归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())

如果他们没有孩子,它将不会产生任何结果并继续下一个孩子。

于 2019-06-03T10:54:16.160 回答