首页 > 解决方案 > dis.dis(foo) 中字段的正式名称

问题描述

我有以下代码,

In [4]: def foo():
   ...:     a = 2
   ...:     b = 3
   ...:     return a + b
   ...: 
   ...: 

In [5]: import dis

In [6]: dis.dis(foo)
  2           0 LOAD_CONST               1 (2)
              2 STORE_FAST               0 (a)

  3           4 LOAD_CONST               2 (3)
              6 STORE_FAST               1 (b)

  4           8 LOAD_FAST                0 (a)
             10 LOAD_FAST                1 (b)
             12 BINARY_ADD
             14 RETURN_VALUE

参考字节码:
我知道:
第一列是行号:2、3、4 第三列是操作名称:LOAD_CONST 等
第五列是代码:(2)(a)

第二列怎么样: 0, 2 4, 6, 8...
第四列 1, 0, 2, 1

您能否提供一个提示以查找相关信息?

标签: python

解决方案


第二列是字节码字节索引;每个字节码由 2 个字节组成(一个表示确切的操作码,另一个表示操作码参数值)。它实际上是第 4 列;输出中有两列没有当前值。

对于您的函数,您可以找到包含字节码作为__code__.co_code属性的字节串:

>>> foo.__code__.co_code
b'd\x01}\x00d\x02}\x01|\x00|\x01\x17\x00S\x00'

b'd\x01'LOAD_CONST 1b'}\x00'STORE_FAST 0,等等。

这记录在dis.disco()函数下:

输出分为以下列:

  1. 行号,用于每行的第一条指令
  2. 当前指令,表示为-->
  3. 带标签的指令,用>>,表示
  4. 指令的地址,
  5. 操作代码名称,
  6. 操作参数,和
  7. 括号中参数的解释。

当您使用时dis.dis(),第 2 列(当前指令)将始终为空。

列#3,标记的指令,在有循环或测试时使用。例如:

>>> dis.dis('if foo:\n    for i in it:\n        print(i)\nelse: print(bar)')
  1           0 LOAD_NAME                0 (foo)
              2 POP_JUMP_IF_FALSE       28

  2           4 SETUP_LOOP              30 (to 36)
              6 LOAD_NAME                1 (it)
              8 GET_ITER
        >>   10 FOR_ITER                12 (to 24)
             12 STORE_NAME               2 (i)

  3          14 LOAD_NAME                3 (print)
             16 LOAD_NAME                2 (i)
             18 CALL_FUNCTION            1
             20 POP_TOP
             22 JUMP_ABSOLUTE           10
        >>   24 POP_BLOCK
             26 JUMP_FORWARD             8 (to 36)

  4     >>   28 LOAD_NAME                3 (print)
             30 LOAD_NAME                4 (bar)
             32 CALL_FUNCTION            1
             34 POP_TOP
        >>   36 LOAD_CONST               0 (None)
             38 RETURN_VALUE

有 4 个跳转目标,其中几个操作码可以触发跳转到其中一个位置。它们用作视觉标记以方便阅读。


推荐阅读