python - 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
您能否提供一个提示以查找相关信息?
解决方案
第二列是字节码字节索引;每个字节码由 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 1
,b'}\x00'
是STORE_FAST 0
,等等。
这记录在dis.disco()
函数下:
输出分为以下列:
- 行号,用于每行的第一条指令
- 当前指令,表示为
-->
,- 带标签的指令,用
>>
,表示- 指令的地址,
- 操作代码名称,
- 操作参数,和
- 括号中参数的解释。
当您使用时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 个跳转目标,其中几个操作码可以触发跳转到其中一个位置。它们用作视觉标记以方便阅读。
推荐阅读
- junit4 - 为什么stringbuilder在线程同时读写时不抛出并发修改异常
- mongodb - 如何返回由 MongoDB 的 find_and_modify() 选择和修改的数组元素?
- django - 我如何在管理面板中显示所有字段 - Django
- node.js - 在 Node.js 中管理多个获取请求
- jquery - Jquery/ajax 未捕获提交事件
- node.js - 使用 node.js 在 MSSQL Server 中以正确格式插入接收到的 unix 时间戳
- java - 名称为 [DEFAULT] 的 FirebaseApp 不存在。使用 App Engine 托管。(弹簧靴)
- javascript - 整数和字符串 Javascript
- javascript - 为什么 JS 允许在数组中使用负索引?
- c# - Dotnet 在 Dockerfile 中恢复 GitHub 包