大家好,我是正在实战各种 AI 项目的程序员晚枫。
字节码如何在虚拟机中执行?理解栈式虚拟机的原理。这一讲,揭开 Python 虚拟机的核心机制。
📖 开篇:Python 代码是如何运行的?
我们写的 Python 代码,不会被直接执行,而是经过了这个过程:
1 | 源代码 (.py) |
CPython 的虚拟机是一个栈式虚拟机(Stack-based VM),所有操作都在操作数栈上进行。
🖥️ 虚拟机架构
核心:ceval.c
1 | // Python/ceval.c |
主循环的三个步骤
1 | fetch → 从内存读取指令(PC++) |
📊 栈式虚拟机工作原理
操作数栈
虚拟机有一个栈(Stack),所有操作都在这个栈上进行:
1 | 执行 1 + 2: |
实际演示
1 | import dis |
1 | 2 0 LOAD_FAST 0 (a) |
每条指令对应的栈操作:
1 | LOAD_FAST 0 → Stack: [a] |
📚 栈帧结构
每个函数调用都有一个对应的栈帧:
1 | struct _frame { |
调用栈示例
1 | def a(): |
1 | 调用栈: |
🔍 代码对象(PyCodeObject)
1 | typedef struct { |
查看代码对象
1 | def greet(name, greeting="Hello"): |
⚡ 指令执行速度
指令分派开销
1 | // Python 3.10 及之前:巨大的 switch 语句 |
Python 3.11 的字节码优化让平均执行速度快了 10-15%,就是这个原因。
💡 本节作业
- 用
dis分析一个复杂函数的字节码,画出栈操作过程 - 打印
add.__code__的所有属性,理解代码对象的结构 - 思考:为什么 Python 3.11 的字节码指令比之前少了?
🎯 本讲总结
虚拟机架构:栈式虚拟机,通过 switch 分派执行字节码指令。
操作数栈:所有操作都在栈上进行(压栈、出栈、运算)。
栈帧结构:包含命名空间、执行状态、操作数栈,是函数调用的载体。
代码对象:包含字节码、常量池、变量名等编译产物。
📚 推荐教材
《Python 编程从入门到实践(第 3 版)》 | 《流畅的 Python(第 2 版)》 | 《CPython 设计与实现》
🔗 课程导航
← 上一讲:字节码编译 | 下一讲:常见字节码指令 →
💬 联系我
| 平台 | 账号/链接 |
|---|---|
| 微信 | 扫码加好友 |
| B 站 | Python 自动化办公社区 |
主营业务:AI 编程培训、企业内训、技术咨询