首页 新闻 会员 周边 捐助

.py程序编译为PyCodeObject对象

0
[已解决问题] 解决于 2025-08-11 19:53

一个Code Block生成一个PyCodeObject,进入一个名字空间成为进入一个Code Block。如下.py文件编译完成后会生成三个PyCodeObject,一个对应整个.py文件一个对应Class A,一个对应def Fun。实际这三个code对象是嵌套的,后两个code对象位于第一个code对象的co_consts属性中。其实,字节码位于co_code中。

Python 编译模型的一个关键点:每个代码块(code block)都会生成一个独立的 PyCodeObject,并且这些对象之间是嵌套关系:
模块级代码 → 一个 PyCodeObject
类定义体 → 另一个 PyCodeObject(嵌在模块的 co_consts 中)
函数体 → 第三个 PyCodeObject(同样嵌在模块的 co_consts 中)

python -m dis test.py
你会看到输出里:
模块级字节码(0 LOAD_BUILD_CLASS 等)
MAKE_FUNCTION 指令引用了 fun 的 code object
LOAD_BUILD_CLASS 时引用了 A 的 code object

_java_python的主页 _java_python | 小虾三级 | 园豆:738
提问于:2025-08-11 19:50
< >
分享
最佳答案
0

在 CPython 的源码里,“Code Block” 是一个非常明确、无歧义的语法概念,而不是“缩进”、“空行”之类的视觉概念。
只要记住一句话:
凡是语法上需要独立“作用域 + 字节码”的地方,解释器就会为它新建一个 PyCodeObject,也就是一个 Code Block。
官方源码里的判定(compile.c)
在 compile.c 中,真正触发“新建 PyCodeObject”的函数是

static PyCodeObject *compiler_makecode(struct compiler *c, ...)

编译器在遍历 AST 时,每遇到下列 AST 节点就会调用一次该函数,于是:
语法结构 AST 节点类型 是否新建 Code Block
模块顶层 Module ✅(模块 Code Block)
函数定义 FunctionDef ✅
类定义 ClassDef ✅
推导式* ListComp/SetComp/… ✅(3.X 起)
Lambda Lambda ✅
生成器表达式 GeneratorExp ✅
if / for / while / try / with If/For/While/… ❌(共用一个模块 Code Block)
推导式在 2.X 里不算独立 Code Block,3.X 开始算,因此有自己的局部变量空间。


分界线到底在哪里?
Code Block 的边界 = 语法上需要独立作用域 + 字节码的结构(Module、FunctionDef、ClassDef、推导式、Lambda)。
其他语句(if、for、try 等)不生成新的 Code Block,它们只是同一块字节码里的跳转指令而已。

_java_python | 小虾三级 |园豆:738 | 2025-08-11 19:52
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册