dis是python自带的零依赖字节码反汇编工具,通过dis.dis()传入函数对象可输出人类可读的栈式虚拟机指令序列,用于精准观察执行逻辑而非猜测;错误传入调用结果会报typeerror,load_/store_/call_类指令是分析变量行为与函数调用的关键。

直接看字节码比猜执行顺序更可靠,dis 是 Python 自带的、零依赖的底层观察工具。
用 dis.dis() 快速反编译函数或代码块
最常用也最直接的方式:把函数对象传进去,它会打印出人类可读的字节码指令序列。
常见错误是传入函数调用结果(比如 dis.dis(foo())),这会报 TypeError: don't know how to disassemble NoneType object —— 因为 dis.dis() 需要的是可调用对象本身,不是它的返回值。
- ✅ 正确写法:
dis.dis(foo)或dis.dis(lambda x: x + 1) - ✅ 也能处理字符串代码:
dis.dis("a = 1; b = a * 2")(注意:这是动态编译,不带源码行号) - ⚠️ 注意缩进:字符串形式中若含多行语句,需保证合法 Python 语法(例如用分号或换行,但不能混用不匹配的缩进)
关注 LOAD_*、STORE_* 和 CALL_* 这三类关键指令
Python 字节码本质是栈式虚拟机指令,真正影响逻辑走向的是变量加载、存储和函数调用行为。比如:
def add(a, b):
return a + b
dis.dis(add)
输出里你会看到 LOAD_FAST(从局部变量槽取值)、BINARY_ADD(执行加法)、RETURN_VALUE(返回栈顶)。而 LOAD_GLOBAL 出现频繁,往往意味着变量未声明或作用域查找开销大;CALL_FUNCTION 后紧跟大量 LOAD_*,说明参数求值顺序是从左到右(这点在有副作用的表达式里很关键)。
快速生成专业的 Python 脚本和应用代码。一键创建完整项目结构,支持CLI、API、爬虫、Bot、Django等多种项目类型,包含完整的项目结构、配置文件、依赖管理、测试、README和文档。
- 变量未声明时,
a可能触发LOAD_GLOBAL而非LOAD_FAST,性能差且易被同名全局变量干扰 -
STORE_SUBSCR对应x[i] = v,不是STORE_FAST,说明目标不是简单变量赋值 - 列表推导式会生成嵌套函数,
dis.dis()默认不展开,得对生成的<genexpr></genexpr>对象单独再 dis
用 dis.get_instructions() 获取结构化字节码数据
当需要程序化分析(比如统计某类指令出现次数、定位特定操作位置),get_instructions() 返回的是 Instruction 对象迭代器,比纯文本输出更容易处理。
每个 Instruction 包含 opname(如 'BINARY_ADD')、arg(原始参数值)、argval(解析后的值,如函数名、常量)、starts_line(对应源码行号)等字段。
- 想查所有函数调用点:
[i for i in dis.get_instructions(func) if i.opname.startswith('CALL_')] -
i.argval对LOAD_CONST是实际常量,对LOAD_METHOD是方法名字符串,别直接拿i.arg当值用 - 同一行多个语句(如
a=1; b=2)可能共享一个starts_line,不能靠它唯一定位逻辑单元
字节码差异常暴露 Python 版本或优化行为
CPython 3.11 引入了“specializing”字节码(如 LOAD_ATTR_INSTANCE),而老版本统一用 LOAD_ATTR;3.12 进一步调整了 CALL 指令变体。这些变化直接影响性能分析结论。
另外,-O(优化模式)下,assert 语句完全消失,__debug__ 相关分支被剥离 —— 如果你没在相同运行模式下 dis,看到的就不是真实执行流。
- 检查当前解释器是否启用优化:
__debug__值为False时,dis输出里不会有ASSERT相关指令 - 不同版本间指令数可能差很多(比如 3.11 的自适应指令会让简单属性访问快一倍,但字节码行数反而变少)
- PyPy 或 Cython 编译后的函数无法用
dis查看(抛TypeError: don't know how to disassemble builtin_function_or_method)
字节码不是万能解码器——闭包变量、描述符协议、C 扩展逻辑都不会出现在 dis 输出里;但只要代码路径落在纯 Python 函数内,它就是最轻量、最真实的执行快照。动手前先确认你在分析的对象确实是 Python 层函数,而不是被装饰器或代理层包裹过的黑盒。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










