第 7 讲:字节码编译器——从 AST 到字节码的转换过程
第 7 讲:字节码编译器——从 AST 到字节码的转换过程

大家好,我是正在实战各种 AI 项目的程序员晚枫。

AST 如何变成字节码?理解 Python 代码的编译过程。

如果把 Tokenizer 比作认字,Parser 比作造句,那么 Compiler 就是把句子翻译成机器能理解的指令。这个翻译过程就是编译。


⚙️ 编译流程

从 AST 到字节码,经历以下几个步骤:

1
2
3
4
5
6
7
8
9
10
11
AST(抽象语法树)

符号表生成(变量作用域分析)

CFG(控制流图)生成

字节码生成

优化(窥孔优化)

.pyc 文件

符号表生成

编译器首先要分析代码中的作用域:哪些是局部变量,哪些是全局变量,哪些是自由变量(闭包中使用)。

1
2
3
4
5
6
7
# 示例代码
x = 1 # 全局变量

def foo():
y = 2 # 局部变量
def bar():
print(x, y) # x 是全局变量,y 是自由变量

符号表记录了每个变量的作用域信息,这些信息会影响字节码的生成。

控制流图(CFG)

CFG 是代码的图形表示,展示了程序的执行路径:

1
2
3
4
5
6
7
8
9
10
11
    [入口]

[x = 1]

[if 条件]
/ \
↓ ↓
[then 分支] [else 分支]
\ /
↓ ↓
[出口]

CFG 帮助编译器理解代码的控制流,从而生成正确的跳转指令。

字节码生成

遍历 CFG,为每个节点生成对应的字节码指令:

1
2
3
4
5
6
7
8
9
# Python 代码
def add(a, b):
return a + b

# 对应的字节码
0 LOAD_FAST 0 (a)
2 LOAD_FAST 1 (b)
4 BINARY_ADD
6 RETURN_VALUE

窥孔优化

编译器会进行一些简单的优化:

1
2
3
4
5
# 优化前
x = 1 + 2 # 先加载 1,再加载 2,然后相加

# 优化后(常量折叠)
x = 3 # 直接加载结果 3

这种优化被称为"窥孔优化",因为它只关注局部的、小范围的优化。


🔍 查看字节码

使用 dis 模块

1
2
3
4
5
6
import dis

def add(a, b):
return a + b

dis.dis(add)

输出:

1
2
3
4
2           0 LOAD_FAST                0 (a)
2 LOAD_FAST 1 (b)
4 BINARY_ADD
6 RETURN_VALUE

字节码含义

偏移指令参数含义
0LOAD_FAST0加载局部变量 a
2LOAD_FAST1加载局部变量 b
4BINARY_ADD-执行加法
6RETURN_VALUE-返回结果

字节码文件

编译后的字节码保存在.pyc 文件中:

1
2
__pycache__/
└── module.cpython-311.pyc

.pyc 文件包含:

  • 魔数(标识 Python 版本)
  • 时间戳
  • 序列化后的代码对象

🎯 本讲总结

通过本讲,我们理解了:

编译流程:AST→符号表→CFG→字节码→优化的完整过程。

符号表:记录变量作用域信息。

控制流图:展示程序执行路径。

字节码生成:遍历 CFG 生成指令。

查看字节码:使用 dis 模块分析字节码。


📚 推荐教材

《Python 编程从入门到实践(第 3 版)》 | 《流畅的 Python(第 2 版)》 | 《CPython 设计与实现》

学习路线: 零基础 → 《从入门到实践》 → 《流畅的 Python》 → 本门课程 → 《CPython 设计与实现》


🔗 课程导航

上一讲:语法分析与 AST 生成 | 下一讲:字节码执行


💬 联系我

平台账号/链接
微信扫码加好友
B 站Python 自动化办公社区

主营业务:AI 编程培训、企业内训、技术咨询

🎓 AI 编程实战课程

想系统学习 AI 编程?程序员晚枫的 AI 编程实战课 帮你从零上手!