在Python AST中,是否可以使用ast.NodeVisitor两次访问节点或更改遍历顺序?

6
NodeVisitor遍历AST并深度优先地访问每个节点,仅在进入时访问每个节点。因此,使用它来做一些严肃的事情是有问题的。是否可能改变它的默认行为?
2个回答

13
也许有人对DSblizzard提出的建议感兴趣,所以这里是我草拟的一个例子,展示如何实现他的建议:

可能有些人会对一些简要的例子感兴趣,这里是我的一个例子,展示了如何实现DSblizzard提出的建议:

import ast

class RecursiveVisitor(ast.NodeVisitor):
    """ example recursive visitor """

    def recursive(func):
        """ decorator to make visitor work recursive """
        def wrapper(self,node):
            func(self,node)
            for child in ast.iter_child_nodes(node):
                self.visit(child)
        return wrapper

    @recursive
    def visit_Assign(self,node):
        """ visit a Assign node and visits it recursively"""
        print(type(node).__name__)

    @recursive
    def visit_BinOp(self, node):
        """ visit a BinOp node and visits it recursively"""
        print(type(node).__name__)

    @recursive
    def visit_Call(self,node):
        """ visit a Call node and visits it recursively"""
        print(type(node).__name__)

    @recursive
    def visit_Lambda(self,node):
        """ visit a Function node """
        print(type(node).__name__)

    @recursive
    def visit_FunctionDef(self,node):
        """ visit a Function node and visits it recursively"""
        print(type(node).__name__)

    @recursive
    def visit_Module(self,node):
        """ visit a Module node and the visits recursively"""
        pass

    def generic_visit(self,node):
        pass

class SimpleVisitor(ast.NodeVisitor):
    """ simple visitor for comparison """

    def recursive(func):
        """ decorator to make visitor work recursive """
        def wrapper(self,node):
            func(self,node)
            for child in ast.iter_child_nodes(node):
                self.visit(child)
        return wrapper

    def visit_Assign(self,node):
        """ visit a Assign node """
        print(type(node).__name__)

    def visit_BinOp(self, node):
        """ visit a BinOp node """
        print(type(node).__name__)

    def visit_Call(self,node):
        """ visit a Call node """
        print(type(node).__name__)

    def visit_Lambda(self,node):
        """ visit a Function node """
        print(type(node).__name__)

    def visit_FunctionDef(self,node):
        """ visit a Function node """
        print(type(node).__name__)

    @recursive
    def visit_Module(self,node):
        """ visit a Module node and the visits recursively, otherwise you
        wouldn't see anything here"""
        pass

    def generic_visit(self,node):
        pass

# usage example
a = """
b= lambda x: x*5 +5
def hhh(u):
    b=19
    return u*b
m=hhh(9*4+5)
"""

recursive_visitor = RecursiveVisitor()
simple_visitor = SimpleVisitor()
tree = ast.parse(a)
print('\nvisit recursive\n')
recursive_visitor.visit(tree)
print('\nvisit simple\n')
simple_visitor.visit(tree)

希望有人会发现这很有用。

你的代码节省了我的时间。谢谢。https://youtrack.jetbrains.com/issue/PY-53000/Disable-inspections-in-docstrings#focus=Comments-27-6455616.0-0 - Denis Barmenkov

6

不行,你应该自己编写访问器。递归访问所有节点相当简单,因此,如果ast模块的功能不能满足你的要求(在这种情况下,模块中没有做你想做的事情),自己做也不是很难。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接