使用Python ast模块访问语法树中的节点

时间:2011-02-09 16:38:48

标签: python parsing abstract-syntax-tree

我正在玩python ast(抽象语法树)。

我写了以下内容,它访问了AST的所有节点。

import ast

class Py2Neko(ast.NodeVisitor):
    def generic_visit(self, node):
              print type(node).__name__
              ast.NodeVisitor.generic_visit(self, node)

       def visit_Name(self, node):
              print 'Name :', node.id

       def visit_Num(self, node):
              print 'Num :', node.__dict__['n']

       def visit_Str(self, node):
              print "Str :", node.s

if __name__ == '__main__':

    node = ast.parse("a = 1 + 2")

    print ast.dump(node)

    v = Py2Neko()
    v.visit(node)

然后向Py2Neko类添加了一些方法

def visit_Print(self, node):
    print "Print :"

def visit_Assign(self, node):
    print "Assign :"

def visit_Expr(self, node):
    print "Expr :"

但是当它遇到“打印”声明或表达或表达时,它似乎停止了,并且不会更进一步。

输出:

Module(body=[Assign(targets=[Name(id='a', ctx=Store())], value=BinOp(left=Num(n=1), op=Add(),       right=Num(n=2)))])
Module
Assign :

有人可以告诉我我做错了什么。

我正在使用Python 2.6.6

2 个答案:

答案 0 :(得分:11)

由于您的visit_Assign方法未显式处理Assign节点的子节点,因此语法树的遍历将在那里停止。

如果您在ast.py的实现中查看NodeVisitor.generic_visit方法,您将看到它循环遍历当前节点的子节点。因此,您可以从需要处理子进程的每个方法中显式调用基类generic_visit方法:

import ast

class Py2Neko(ast.NodeVisitor):
    def generic_visit(self, node):
        print type(node).__name__
        ast.NodeVisitor.generic_visit(self, node)

    def visit_Name(self, node):
        print 'Name :', node.id

    def visit_Num(self, node):
        print 'Num :', node.__dict__['n']

    def visit_Str(self, node):
        print "Str :", node.s

    def visit_Print(self, node):
        print "Print :"
        ast.NodeVisitor.generic_visit(self, node)

    def visit_Assign(self, node):
        print "Assign :"
        ast.NodeVisitor.generic_visit(self, node)

    def visit_Expr(self, node):
        print "Expr :"
        ast.NodeVisitor.generic_visit(self, node)

if __name__ == '__main__':
    node = ast.parse("a = 1 + 2")

    print ast.dump(node)

    v = Py2Neko()
    v.visit(node)

答案 1 :(得分:4)

对于非终端节点,您的访问功能必须访问孩子。有关更多信息,请参阅Simple example of how to use ast.NodeVisitor?