Python AST –抽象语法树

时间:2020-02-23 14:42:27  来源:igfitidea点击:

抽象语法树是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解释器