我在理解Python的字节码及其dis
模块时遇到了很多困难。
import dis
def func():
x = 1
dis.dis(func)
在解释器中输入上面的代码会产生以下输出:
0 LOAD_CONST 1(1)
3 STORE_FAST 0(x)
6 LOAD_CONST 0(NONE)
9 RETURN_VALUE
E.g:
LOAD_CONST
,STORE_FAST
以及0
,3
,6
和9
等数字的含义是什么?
我非常感谢能够找到这些信息的特定资源。
答案 0 :(得分:33)
字节码前面的数字是原始二进制字节码的偏移量:
>>> func.__code__.co_code
'd\x01\x00}\x00\x00d\x00\x00S'
某些字节码带有影响每个字节码工作方式的附加信息(参数),偏移量告诉您在字节流中找到字节码的位置。
例如,LOAD_CONST
字节码(ASCII d
,十六进制64)之后是另外两个字节,用于编码对与字节码相关联的常量的引用。因此,STORE_FAST
操作码(ASCII }
,十六进制7D)位于索引3处。
dis
module documentation列出了每条指令的含义。对于LOAD_CONST
,它说:
将
co_consts[consti]
推入堆栈。
指的是始终与代码对象一起出现的co_consts
结构;编译器构造:
>>> func.__code__.co_consts
(None, 1)
操作码从该结构加载索引1(字节码中的01 00字节编码为1),dis
已经为您查找;它是值1
。
下一条指令STORE_FAST
被描述为:
将TOS存储到本地
co_varnames[var_num]
。
这里 TOS 指的是堆栈顶部;请注意,LOAD_CONST
只是将某些内容推送到堆栈,即1
值。 co_varnames
是另一种结构;它引用局部变量名,操作码引用索引0:
>>> func.__code__.co_varnames
('x',)
dis
也查了一下,您在代码中使用的名称是x
。因此,此操作码将1
存储到x
。
另一个LOAD_CONST
从索引0加载None
到堆栈,然后是RETURN_VALUE
:
使用TOS返回函数的调用者。
因此该指令占据堆栈的顶部(None
常量)并从此代码块返回。 None
是没有明确return
语句的函数的默认返回值。
您省略了dis
输出中的内容,行号:
>>> dis.dis(func)
2 0 LOAD_CONST 1 (1)
3 STORE_FAST 0 (x)
6 LOAD_CONST 0 (None)
9 RETURN_VALUE
注意第一行的2
;这是原始源中包含用于这些指令的Python代码的行号。 Python代码对象具有co_lnotab
和co_firstlineno
属性,可用于将字节码映射回原始源中的行号。 dis
在显示反汇编时会为您执行此操作。