前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >python ast模块

python ast模块

作者头像
周小董
发布2019-03-25 11:23:39
1.9K0
发布2019-03-25 11:23:39
举报
文章被收录于专栏:python前行者python前行者

我们知道python解析执行的过程大概是这样的:

词法分析 –> 具体语法树 –> 抽象语法树 –> 控制流图 –> 字节码 –> 执行

其中,抽象语法树可以用ast模块建立出来.

首先第一个问题是, 这个ast模块有什么用呢? ast提供了访问和修改上述中抽象语法树的功能.可以做一些比如测试,代码生成,静态分析等等. 比如pylint, pythonscope就用到这个功能.

ast这个module提供了一些访问节点的接口:

ast.iter_fields(node) Yield a tuple of (fieldname, value) for each field in node._fields that is present on node. ast.iter_child_nodes(node) Yield all direct child nodes of node, that is, all fields that are nodes and all items of fields that are lists of nodes. ast.walk(node) Recursively yield all descendant nodes in the tree starting at node (including node itself), in no specified order. This is useful if you only want to modify nodes in place and don’t care about the context.

这里只列出了几个遍历的函数.如果要遍历整个树呢?

class ast.NodeVisitor 和 class ast.NodeTransformer

这两个的区别就是visit是修改原来的node,transformer可以替换一个新的node.

那么我们现在做一个功能,把py文件中的字符串 “123456” 全部替换为 “45678”

class MyVisitor(ast.NodeVisitor):
    def visit_Str(self, node):
        print 'Found string "%s"' % node.s
        if node.s == "123456":
            node.s = "45678"

    def visit_FunctionDef(self, node):
        print 'Found function ', node._fields


MyVisitor().visit(mast)

import codegen
print codegen.to_source(mast)

查看输出:

a = 1
b = 2
c = a + b


class c1(object):
    c_var_int = 1
    c_var_str = '45678'

    def __init__(self):
        return

    def func1(self, x, y):
        return

已经替换.

visitor的遍历方法就是对于每一个node, 去找 visit_node类名 这个函数,找到了就访问,找不到就找generic_visit这个函数.

transform也是一样.

好,现在我们做这样一个事情.对于某个class, 在发生函数调用的时候,打出一条log,这种情况在调试的时候是很常见的吧.那么这个可以用getattr来做,就是getattr的时候判断是不是一个函数,如果是函数就打出log,这样很好可是不能打出参数.也可以用decorator来做,就比较麻烦,就要挨个去加.

源文件是这样的:

class c1(object):
    c_var_int = 1 
    c_var_str = "123456"
    def __init__(self):
        return

    def func1(self, x, y): 
        c = x + y 
        return c



class c2(c1, object):
    pass

def gfunc1(x, y): 
    return x*x + y*y 

获取语法树

ast模块的基本使用是非常简单的,我们可以通过如下代码快速得到一棵抽象语法树:

import ast
root_node = ast.parse("print 'hello world'")
root_node -> <_ast.Module object at 0x9e3df6c>

通过ast的parse方法得到ast tree的根节点root_node, 我看可以通过根节点来遍历语法树,从而对python代码进行分析和修改。

ast.parse(可以直接查看ast模块的源代码)方法实际上是调用内置函数compile进行编译,如下所示:

def parse(source, filename='<unknown>', mode='exec'):
    """
    Parse the source into an AST node.
    Equivalent to compile(source, filename, mode, PyCF_ONLY_AST).
    """
    return compile(source, filename, mode, PyCF_ONLY_AST)

传递给compile特殊的flag = PyCF_ONLY_AST, 来通过compile返回抽象语法树。

参考:https://zhuanlan.zhihu.com/p/21945624 https://blog.csdn.net/ma89481508/article/details/56017697

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018年08月06日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 获取语法树
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档