26

我很难理解 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

例如:

LOAD_CONST,和等STORE_FAST数字是什么意思?0369

非常感谢我可以在其中找到此信息的特定资源。

4

1 回答 1

44

字节码之前的数字是原始二进制字节码的偏移量:

>>> func.__code__.co_code
'd\x01\x00}\x00\x00d\x00\x00S'

一些字节码带有影响每个字节码如何工作的附加信息(参数),偏移量告诉您在字节流中的哪个位置找到了字节码。

例如,LOAD_CONST字节码(ASCII d,十六进制 64)后跟两个额外的字节,编码对与字节码关联的常量的引用。结果,STORE_FAST操作码(ASCII },十六进制 7D)在索引 3 处找到。

dis模块文档列出了每条指令的含义。对于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. 因此,此操作码存储1x.

另一个从索引 0LOAD_CONST加载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_lnotabco_firstlineno属性,可让您将字节码映射回原始源代码中的行号。dis在显示反汇编时为您执行此操作。

于 2013-10-24T08:03:16.397 回答