Python AST 模块实战演示

2025-11-23 06:50
文章标签 python ast 演示 模块 实战

本文主要是介绍Python AST 模块实战演示,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

《PythonAST模块实战演示》Python的ast模块提供了一种处理Python代码的强大工具,通过解析代码生成抽象语法树(AST),可以进行代码分析、修改和生成,接下来通过本文给大家介绍Py...

pythonast(Abstract Syntax Tree,抽象语法树)模块是一个用于处理 Python 代码的强大工具。它允许你将代码转换为一种结构化的树形表示,从而可以进行分析、修改甚至生成新的代码。这对于理解代码的内部结构、构建开发工具或进行代码自动化处理非常有帮助。

什么是抽象语法树(AST)

在深入了解 ast 模块之前,我们先简单理解一下抽象语法树(AST)的概念。当 Python 解释器执行代码时,它首先需要理解代码的结构。这个过程大致是:源代码 -> 词法分析(生成令牌流) -> 语法分析(生成 AST) -> 字节码 -> 执行。AST 就是源代码抽象语法结构的树状表示,它过滤掉了像空格、注释这类非本质的细节,专注于代码的逻辑结构。每个节点代表代码中的一个结构(例如,一个表达式、一个语句、一个函数定义等)。

ast 模块的核心作用就是在这棵“语法树”上工作,让你能在代码被编译成字节码之前,洞察和操作其本质。

️ ast 模块的核心用法

ast 模块提供了一系列函数和类来创建、遍历和修改 AST。

1. 解析代码生成 AST

使用 ast.parse() 函数可以将字符串形式的 Python 代码解析成一棵 AST 的根节点(通常是 ast.Module 节点)。

import ast
code = """
def greet(name):
    print(f"Hello, {name}!")
"""
tree = ast.parse(code)  # 得到 AST

2. 查看 AST 结构

生成 AST 后,可以使用 ast.dump() 函数将其以文本形式打印出来,以便查看整个树的结构。

print(ast.dump(tree, indent=4))

这会输出一个结构化的文本,展示所有的节点、它们的属性以及嵌套关系。

3. 遍历 AST

要分析 AST,你需要遍历它的节点。ast 模块提供了两种主要方式:

  • 使用 ast.NodeVisitor 类:这是最常用和推荐的方法。你可以创建一个继承自 ast.NodeVisitor 的类,并为感兴趣的节点类型定义 visit_ 方法(例如 visit_FunctionDef 用于访问函数定义节点)。在方法中,你可以通过 self.generic_visit(node) 来继续遍历当前节点的子节点。
class MyVisitor(ast.Nohttp://www.chinasem.cndeVisitor):
    def visit_FunctionDef(self, node):
        print(f"Found function: {node.name}")
        self.generic_visit(node)  # 继续遍历子节点
visitor = MyVisitor()
visitor.visit(tree)
  • 使用 ast.walk() 函数:这个函数会递归地遍历 AST 中的所有节点,但不关心节点的层级关系。它返回一个生成器,适合当你需要找到所有特定类型的节点时使用。
for node in ast.walk(tree):
    if isinstance(node, ast.FunctionDef):
        print(node.name)

4. 修改 AST

除了分析,你还可以修改 AST。这需要通过继承 as编程t.NodeTransformer 类来实现。它的使用方式和 NodeVisitor 类似,但关键区别在于,visit_ 方法需要返回一个节点。你可以返回:

  • 原节点:不做任何修改。
  • 新节点:替换原节点。
  • None:删除该节点。

一个经典的例子是将代码中的所有加法操作 + 替换为减法操作 -

class AddToSubTransformer(ast.NodeTransformer):
    def visit_BinOp(self, node):
        if isinstance(node.op, ast.Add):
            # 创建一个新的操作符节点,将加法改为减法
            node.op = ast.Sub()
        return self.generic_visit(node)  # 返回修改后的节点,并继续遍历其子节点
transformer = AddToSubTransformer()
new_tree = transformer.visit(tree)

重要提示:在创建新节点替换旧节点后,如果新节点缺少源代码位置信息(如行号、列偏移量),需要使用 ast.fix_missing_locations() 函数来修复,否则在编译时可能会出错。

5. 将 AST 编译回代码

修改完 AST 后,你可以通过内置的 compile() 函数将其编译成可执行的 Python 字节码,然后使用 exec()eval() 来运行它。

# 将修改后的 AST 编译成代码对象
code_obj = compile(new_tree, filename='<string>', mode='exec')
# 执行代码对象
exec(code_obj)

此外,从 Python 3.9 开始,标准库提供了 ast.unparse() 函数,可以直AizXghCTwK接将 AST 节点转换回可读的 Python 代码字符串。对于更早的版本,可以使用第三方库如 astor

6. 安全地求值表达式

ast 模块还提供了一个非常实用的函数 ast.literal_eval()。它可以安全地计算一个包含 Python 字面量(如字符串、数字、元组、列表、字典、布尔值等)的表达式字符串,并返回结果。与内置的 eval() 不同,它不会执行任意代码,因此安全得多,非常适合处理来自不可信来源的数据。

safe_result = ast.literal_eval("[1, 2, 3]")  # 结果是列表 [1, 2, 3]

大厂笔试面试如何考察 ast

在大厂的笔试或面试中,对 ast 模块的考察通常不会要求你死记硬背所有的节点类型,而是更注重实践应用php对 Python 机制的理解深度以及解决实际问题的思路

常见的考察方向

  • 基础概念理解
    • 可能会问:AST 在 Python 解释过程中处于哪个阶段?它和字节码有什么区别?
    • 或者:ast.literal_eval()eval() 有什么区别?为什么前者更安全?
  • 代码分析与审计
    • 静态代码检查:让你编写一个简单的检查器,使用 ast.NodeVisitor 来遍历代码,找出潜在问题。例如,检测是否使用了不安全的函数(如 evalexec),或者检查代码风格(如变量命名规范)。
    • 代码复杂度分析:通过分析函数定义、循环、条件分支等节点的数量和嵌套关系,来估算代码的复杂度。
  • 代码转换与自动化
    • 这是考察的重点和难点。面试官可能会给出一个具体的代码重构任务,让你使用 ast.NodeTransformer 来实现自动化。例如:
  • 重命名:将代码中所有特定变量名或函数名进行批量替换。
  • 逻辑替换:如前面提到的,将加法操作改为减法。
  • API 升级:假设某个库的 API 发生了变化,需要你写一个工具自动将旧代码中的函数调用更新为新形式。
  • 网络安全结合
    • 尤其是在安全相关的岗位面试中。可能会给出一段代码,要求你分析其中可能存在的安全漏洞(如 SQL 注入、命令注入点),这需要你能够通过 AST 分析代码的数据流和控制流。

实例分析:面试题模拟

题目:请你使用 ast 模块,编写一个简单的静态分析工具,用于检测一段 Python 代码中是否使用了 eval() 函数。如果使用了,则输出警告信息。

考察点

  • 是否掌握 ast 的基本解析和遍历操作。
  • 是否熟悉 ast.NodeVisitor 的使用。
  • 能否识别函数调用节点(ast.Call)并判断其函数名。

参考实现

import ast
code = """
x = 1
result = eval('1 + 1')
print(eval('2+2'))
"""
class EvalDetector(ast.NodeVisitor):
    def visit_Call(self, node):
        # 检查节点是否是一个函数调用,并且函数名是一个标识符(Name)且id为'eval'
        if isinstance(node.func, ast.Name) and node.func.id == 'eval':
            print(f"Warning: Potential use of eval() found at line {node.lineno}")
        # 继续遍历子节点,以查找嵌套调用等情况
        self.generic_visit(node)
tree = ast.parse(code)
detector = EvalDetector()
detector.visit(tree)

输出

Warning: Potential use of eval() found at line 4
Warning: Potential use of eval() found at line 5

这个例子演示了如何使用 ast.NodeViChina编程sitor 来访问代码中的函数调用节点(ast.Call),并根据条件(函数名为 eval)进行判断和输出。

总结与核心知识点

为了帮助你更好地记忆,我将 ast 模块的核心知识点整理成了下面的表格:

核心概念/操作关键函数/类说明与用途
解析代码ast.parse(source)将源代码字符串解析为 AST 根节点(ast.Module)。
查看结构ast.dump(node)将 AST 节点以字符串形式输出,用于调试。
遍历 ASTast.NodeVisitor通过继承此类并定义 visit_XXX 方法来有选择地访问节点。
遍历 ASTast.walk(node)递归遍历 AST 中的所有节点,不保留层级信息。
修改 ASTast.NodeTransformer通过继承此类,在 visit_XXX 方法中返回新节点来修改 AST。
编译执行compile(tree, ...)将 AST 编译为可执行的代码对象。
反解析ast.unparse(node) (Python 3.9+)将 AST 节点转换回等价的 Python 代码字符串。
安全求值ast.literal_eval()安全地求值字面量表达式(字符串、列表、数字等),避免任意代码执行风险。
修复位置ast.fix_missing_locations(node)为新建或修改的节点补充行号等位置信息,确保能正确编译。

到此这篇关于Python AST 模块实战解析的文章就介绍到这了,更多相关python ast 模块内容请搜索China编程(www.chinasem.cn)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程China编程(www.chinasem.cn)!

这篇关于Python AST 模块实战演示的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1156244

相关文章

Python+FFmpeg实现视频自动化处理的完整指南

《Python+FFmpeg实现视频自动化处理的完整指南》本文总结了一套在Python中使用subprocess.run调用FFmpeg进行视频自动化处理的解决方案,涵盖了跨平台硬件加速、中间素材处理... 目录一、 跨平台硬件加速:统一接口设计1. 核心映射逻辑2. python 实现代码二、 中间素材处

python中的flask_sqlalchemy的使用及示例详解

《python中的flask_sqlalchemy的使用及示例详解》文章主要介绍了在使用SQLAlchemy创建模型实例时,通过元类动态创建实例的方式,并说明了如何在实例化时执行__init__方法,... 目录@orm.reconstructorSQLAlchemy的回滚关联其他模型数据库基本操作将数据添

Python实现快速扫描目标主机的开放端口和服务

《Python实现快速扫描目标主机的开放端口和服务》这篇文章主要为大家详细介绍了如何使用Python编写一个功能强大的端口扫描器脚本,实现快速扫描目标主机的开放端口和服务,感兴趣的小伙伴可以了解下... 目录功能介绍场景应用1. 网络安全审计2. 系统管理维护3. 网络故障排查4. 合规性检查报错处理1.

Python轻松实现Word到Markdown的转换

《Python轻松实现Word到Markdown的转换》在文档管理、内容发布等场景中,将Word转换为Markdown格式是常见需求,本文将介绍如何使用FreeSpire.DocforPython实现... 目录一、工具简介二、核心转换实现1. 基础单文件转换2. 批量转换Word文件三、工具特性分析优点局

Python中4大日志记录库比较的终极PK

《Python中4大日志记录库比较的终极PK》日志记录框架是一种工具,可帮助您标准化应用程序中的日志记录过程,:本文主要介绍Python中4大日志记录库比较的相关资料,文中通过代码介绍的非常详细,... 目录一、logging库1、优点2、缺点二、LogAid库三、Loguru库四、Structlogphp

C++,C#,Rust,Go,Java,Python,JavaScript的性能对比全面讲解

《C++,C#,Rust,Go,Java,Python,JavaScript的性能对比全面讲解》:本文主要介绍C++,C#,Rust,Go,Java,Python,JavaScript性能对比全面... 目录编程语言性能对比、核心优势与最佳使用场景性能对比表格C++C#RustGoJavapythonjav

Python海象运算符:=的具体实现

《Python海象运算符:=的具体实现》海象运算符又称​​赋值表达式,Python3.8后可用,其核心设计是在表达式内部完成变量赋值并返回该值,从而简化代码逻辑,下面就来详细的介绍一下如何使用,感兴趣... 目录简介​​条件判断优化循环控制简化​推导式高效计算​正则匹配与数据提取​性能对比简介海象运算符

python项目环境切换的几种实现方式

《python项目环境切换的几种实现方式》本文主要介绍了python项目环境切换的几种实现方式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录1. 如何在不同python项目中,安装不同的依赖2. 如何切换到不同项目的工作空间3.创建项目

python项目打包成docker容器镜像的两种方法实现

《python项目打包成docker容器镜像的两种方法实现》本文介绍两种将Python项目打包为Docker镜像的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要... 目录简单版:(一次成功,后续下载对应的软件依赖)第一步:肯定是构建dockerfile,如下:第二步

Python + Streamlit项目部署方案超详细教程(非Docker版)

《Python+Streamlit项目部署方案超详细教程(非Docker版)》Streamlit是一款强大的Python框架,专为机器学习及数据可视化打造,:本文主要介绍Python+St... 目录一、针对 Alibaba Cloud linux/Centos 系统的完整部署方案1. 服务器基础配置(阿里