Python AST –抽象语法树
抽象语法树是Python中非常强大的功能。
Python AST模块允许我们与Python代码本身进行交互并对其进行修改。
Python AST模块
使用Python AST模块,我们可以做很多事情,例如修改Python代码并检查它。
在将代码编译成" bytecode"形式之前,可以对其进行解析和修改。
重要的是要理解,每个抽象语法树都将Python代码中的每个元素表示为一个对象。
我们将在接下来的部分中详细了解这一点。
让我们尝试一下真实的代码。
代码编译模式
正如我们在上面的最后一个脚本中提到的mode一样,可以在三种模式下编译Python代码。
他们是:
exec:我们可以使用这种模式执行普通的Python代码。
评估:要评估Python的表达式,此模式将在评估后返回表达式的结果。
single:此模式的工作方式类似于Python Shell,一次执行一个语句。
执行代码
我们可以使用AST模块执行Python代码。
这是一个示例程序:
import ast code = ast.parse("print('Hello world!')") print(code) exec(compile(code, filename="", mode="exec"))
让我们看一下该程序的输出:如上所述,我们在这里使用了exec模式。
评估Python表达式
基于我们上面提到的第二种模式,AST可用于评估Python表达式并获得该表达式的响应。
让我们看一下代码片段:
import ast expression = '6 + 8' code = ast.parse(expression, mode='eval') print(eval(compile(code, '', mode='eval')))
让我们看一下该程序的输出:还可以看到为上面的表达式形成的AST,只需在上面的脚本中添加以下行:
print(ast.dump(code))
构造多行AST
到现在为止,我们只做了一行AST,在上一个示例中,我们还看到了使用转储的外观。
现在,我们将多行Python代码转换为AST。
这是一个示例程序:
import ast tree = ast.parse(''' fruits = ['grapes', 'mango'] name = 'peter' for fruit in fruits: print('{} likes {}'.format(name, fruit)) ''') print(ast.dump(tree))
让我们看一下该程序的输出:我们可以通过修改脚本来访问每个节点:
import ast class NodeVisitor(ast.NodeVisitor): def visit_Str(self, tree_node): print('{}'.format(tree_node.s)) class NodeTransformer(ast.NodeTransformer): def visit_Str(self, tree_node): return ast.Str('String: ' + tree_node.s) tree_node = ast.parse(''' fruits = ['grapes', 'mango'] name = 'peter' for fruit in fruits: print('{} likes {}'.format(name, fruit)) ''') NodeTransformer().visit(tree_node) NodeVisitor().visit(tree_node)
让我们看一下该程序的输出:上面创建的Visitor类实现为每个AST节点调用的方法,而对于Transformer类,它首先为节点调用相应的方法,最后将其替换为该方法的返回值。
我们可以通过添加以下行来在此处执行方法:
tree_node = ast.fix_missing_locations(tree_node) exec(compile(tree_node, '', 'exec'))
何时使用Python AST模块?
许多自动化测试工具,代码覆盖率工具依靠抽象语法树的功能来解析源代码,并发现代码中可能存在的缺陷和错误。
除此之外,AST还用于:
使IDE变得智能化并使其成为众所周知的智能感知功能。
像Pylint这样的工具使用AST执行静态代码分析
自定义Python解释器