python / 3.7.2rc1 / all / library-dis.html

dis — Python 字节码的反汇编程序

源代码: Lib/dis.py


dis模块pass分解支持 CPython bytecode的分析。此模块作为 Importing 的 CPython 字节码在文件Include/opcode.h中定义,并由编译器和解释器使用。

CPython 实现细节: 字节码是 CPython 解释器的实现细节。无法保证不会在 Python 版本之间添加,删除或更改字节码。不应考虑在 Python VM 或 Python 版本之间使用此模块。

在版本 3.6 中更改:每个指令使用 2 个字节。以前,字节数因指令而异。

示例:给定函数myfunc()

def myfunc(alist):
    return len(alist)

以下命令可用于显示myfunc()的反汇编:

>>> dis.dis(myfunc)
  2           0 LOAD_GLOBAL              0 (len)
              2 LOAD_FAST                0 (alist)
              4 CALL_FUNCTION            1
              6 RETURN_VALUE

(“ 2”是行号)。

Bytecode analysis

3.4 版的新Function。

字节码分析 API 允许将 Python 代码片段包装在Bytecode对象中,该对象可轻松访问已编译代码的详细信息。

    • class * dis. Bytecode(* x **,* first_line = None current_offset = None *)
    • 分析与函数,生成器,异步生成器,协程,方法,源代码字符串或代码对象(由compile()返回)相对应的字节码。

这是下面列出的许多Function的便捷包装,其中最值得注意的是get_instructions(),因为在Bytecode实例上进行迭代会产生字节代码操作作为Instruction实例。

如果* first_line *不是None,则表示应该在反汇编代码中为第一个源行报告的行号。否则,直接从反汇编的代码对象中获取源代码行信息(如果有)。

如果* current_offset *不是None,则表示反汇编代码中的指令偏移量。设置此项意味着dis()将针对指定的操作码显示一个“当前指令”标记。

  • 类方法 from_traceback(* tb *)

    • 从给定的 traceback 构造一个Bytecode实例,并将* current_offset *设置为负责异常的指令。
  • codeobj

    • 编译后的代码对象。
  • first_line

    • 代码对象的第一行源代码(如果有)
  • dis ( )

    • 返回字节码操作的格式化视图(与dis.dis()打印相同,但以多行字符串形式返回)。
  • info ( )

    • 返回格式化的多行字符串,其中包含有关代码对象的详细信息,例如code_info()

在版本 3.7 中更改:现在可以处理协程和异步生成器对象。

Example:

>>> bytecode = dis.Bytecode(myfunc)
>>> for instr in bytecode:
...     print(instr.opname)
...
LOAD_GLOBAL
LOAD_FAST
CALL_FUNCTION
RETURN_VALUE

Analysis functions

dis模块还定义了以下分析Function,可将 Importing 直接转换为所需的输出。如果仅执行单个操作,它们将很有用,因此中间分析对象无用:

  • dis. code_info(* x *)
    • 返回格式化的多行字符串,其中包含所提供函数,生成器,异步生成器,协程,方法,源代码字符串或代码对象的详细代码对象信息。

请注意,代码信息字符串的确切内容高度依赖于实现,并且它们在 Python VM 或 Python 版本之间可能会任意更改。

3.2 版中的新Function。

在版本 3.7 中更改:现在可以处理协程和异步生成器对象。

  • dis. show_code(* x **,* file = None *)
    • 将提供的函数,方法,源代码字符串或代码对象的详细代码对象信息打印到* file (如果未指定 file *,则为sys.stdout)。

这是print(code_info(x), file=file)的便捷缩写,意在解释器提示下进行交互式探索。

3.2 版中的新Function。

在版本 3.4 中更改:添加了* file *参数。

  • dis. dis(* x = None **,* file = None depth = None *)
    • 拆卸* x *对象。 * x *可以表示模块,类,方法,函数,生成器,异步生成器,协程,代码对象,源代码字符串或原始字节码的字节序列。对于模块,它将分解所有Function。对于一个类,它将分解所有方法(包括类和静态方法)。对于代码对象或原始字节码序列,每个字节码指令将打印一行。它还递归地反汇编嵌套的代码对象(理解代码,生成器表达式和嵌套函数以及用于构建嵌套类的代码)。在反汇编之前,首先使用compile()内置函数将字符串编译为代码对象。如果未提供任何对象,则此函数将反汇编最后的回溯。

反汇编将作为文本写入提供的* file *参数(如果提供),否则写入sys.stdout

除非* _1,否则最大递归深度受* depth *限制。 depth=0表示没有递归。

在版本 3.4 中更改:添加了* file *参数。

在版本 3.7 中进行了更改:实现了递归拆卸并添加了* depth *参数。

在版本 3.7 中更改:现在可以处理协程和异步生成器对象。

  • dis. distb(* tb = None **,* file = None *)
    • 如果没有pass最后的回溯,则反汇编回溯的堆栈顶部函数。指示导致异常的指令。

反汇编将作为文本写入提供的* file *参数(如果提供),否则写入sys.stdout

在版本 3.4 中更改:添加了* file *参数。

  • dis. disassemble(* code lasti = -1 **,* file = None *)

  • dis. disco(* code lasti = -1 **,* file = None *)

    • 反汇编代码对象,如果提供了* lasti *,则指示最后一条指令。输出分为以下几列:
  • 行号,用于每行的第一条指令

  • 当前指令,表示为-->

  • 标有>>的标记说明,

  • 指令的地址,

  • 操作代码名称,

  • 操作参数,以及

  • 括号中参数的解释。

参数解释可识别局部和全局变量名称,常量值,分支目标和比较运算符。

反汇编将作为文本写入提供的* file *参数(如果提供),否则写入sys.stdout

在版本 3.4 中更改:添加了* file *参数。

  • dis. get_instructions(* x **,* first_line = None *)
    • 在提供的函数,方法,源代码字符串或代码对象中的指令上返回迭代器。

迭代器生成一系列Instruction命名的 Tuples,在提供的代码中给出每个操作的详细信息。

如果* first_line *不是None,则表示应该在反汇编代码中为第一个源行报告的行号。否则,直接从反汇编的代码对象中获取源代码行信息(如果有)。

3.4 版的新Function。

  • dis. findlinestarts(* code *)
    • 此生成器函数使用代码对象* code *的co_firstlinenoco_lnotab属性来查找源代码中行首的偏移量。它们生成为(offset, lineno)对。有关co_lnotab格式以及如何对其进行解码,请参见Objects/lnotab_notes.txt

在版本 3.6 中更改:行号可以减少。以前,它们一直在增长。

  • dis. findlabels(* code *)

    • 在原始编译的字节码字符串* code *中检测所有偏移量,它们是跳转目标,并返回这些偏移量的列表。
  • dis. stack_effect(* opcode oparg = None **,* jump = None *)

    • 用参数* oparg 计算 opcode *的堆栈效果。

如果代码具有跳转目标并且* jump True,则stack_effect()将返回跳转的堆栈效果。如果 jump False,它将返回不跳跃的堆栈效果。如果 jump *为None(默认值),它将返回两种情况的最大叠加效果。

3.4 版的新Function。

在版本 3.8 中更改:添加了* jump *参数。

Python 字节码说明

get_instructions()函数和Bytecode类提供了作为Instruction实例的字节码指令的详细信息:

  • 类别 dis. Instruction

    • 字节码操作的详细信息
  • opcode

    • 用于操作的数字代码,与下面列出的操作码值和Opcode collections中的字节码值相对应。
  • opname

    • 易读的操作名称
  • arg

    • 运算的数字参数(如果有),否则为None
  • argval

    • 解析的 arg 值(如果已知),否则与 arg 相同
  • argrepr

    • 可读的操作参数描述
  • offset

    • 字节码序列内的操作开始索引
  • starts_line

    • 该操作码(如果有)开头的行,否则为None
  • is_jump_target

    • True如果其他代码跳到此处,否则False

3.4 版的新Function。

Python 编译器当前生成以下字节码指令。

General instructions

  • NOP

    • 不执行任何代码。字节码优化器用作占位符。
  • POP_TOP

    • 删除堆栈顶部(TOS)项。
  • ROT_TWO

    • 交换两个最上面的堆栈项。
  • ROT_THREE

    • 将第二个和第三个堆栈项目向上提起一个位置,从上向下移动到位置三。
  • ROT_FOUR

    • 将第二,第三和第四堆物品向上提升一个位置,从顶部向下移动到第四位置。

3.8 版的新Function。

  • DUP_TOP
    • 将引用复制到堆栈顶部。

3.2 版中的新Function。

  • DUP_TOP_TWO
    • 将两个引用复制到堆栈顶部,以相同的 Sequences 保留它们。

3.2 版中的新Function。

Unary operations

一元运算占据堆栈的顶部,应用该运算,然后将结果推回堆栈。

  • UNARY_POSITIVE

    • 实现TOS = +TOS
  • UNARY_NEGATIVE

    • 实现TOS = -TOS
  • UNARY_NOT

    • 实现TOS = not TOS
  • UNARY_INVERT

    • 实现TOS = ~TOS
  • GET_ITER

    • 实现TOS = iter(TOS)
  • GET_YIELD_FROM_ITER

3.5 版中的新Function。

Binary operations

二进制操作从堆栈中删除堆栈的顶部(TOS)和第二高的堆栈项(TOS1)。他们执行操作,然后将结果放回堆栈。

  • BINARY_POWER

    • 实现TOS = TOS1 ** TOS
  • BINARY_MULTIPLY

    • 实现TOS = TOS1 * TOS
  • BINARY_MATRIX_MULTIPLY

    • 实现TOS = TOS1 @ TOS

3.5 版中的新Function。

  • BINARY_FLOOR_DIVIDE

    • 实现TOS = TOS1 // TOS
  • BINARY_TRUE_DIVIDE

    • 实现TOS = TOS1 / TOS
  • BINARY_MODULO

    • 实现TOS = TOS1 % TOS
  • BINARY_ADD

    • 实现TOS = TOS1 + TOS
  • BINARY_SUBTRACT

    • 实现TOS = TOS1 - TOS
  • BINARY_SUBSCR

    • 实现TOS = TOS1[TOS]
  • BINARY_LSHIFT

    • 实现TOS = TOS1 << TOS
  • BINARY_RSHIFT

    • 实现TOS = TOS1 >> TOS
  • BINARY_AND

    • 实现TOS = TOS1 & TOS
  • BINARY_XOR

    • 实现TOS = TOS1 ^ TOS
  • BINARY_OR

    • 实现TOS = TOS1 | TOS

In-place operations

就地操作类似于二进制操作,因为它们删除了 TOS 和 TOS1,并将结果推回堆栈,但是当 TOS1 支持它时,该操作是就地完成的,并且结果 TOS 可能是(但不具有是)原始 TOS1.

  • INPLACE_POWER

    • 实现就地TOS = TOS1 ** TOS
  • INPLACE_MULTIPLY

    • 实现就地TOS = TOS1 * TOS
  • INPLACE_MATRIX_MULTIPLY

    • 实现就地TOS = TOS1 @ TOS

3.5 版中的新Function。

  • INPLACE_FLOOR_DIVIDE

    • 实现就地TOS = TOS1 // TOS
  • INPLACE_TRUE_DIVIDE

    • 实现就地TOS = TOS1 / TOS
  • INPLACE_MODULO

    • 实现就地TOS = TOS1 % TOS
  • INPLACE_ADD

    • 实现就地TOS = TOS1 + TOS
  • INPLACE_SUBTRACT

    • 实现就地TOS = TOS1 - TOS
  • INPLACE_LSHIFT

    • 实现就地TOS = TOS1 << TOS
  • INPLACE_RSHIFT

    • 实现就地TOS = TOS1 >> TOS
  • INPLACE_AND

    • 实现就地TOS = TOS1 & TOS
  • INPLACE_XOR

    • 实现就地TOS = TOS1 ^ TOS
  • INPLACE_OR

    • 实现就地TOS = TOS1 | TOS
  • STORE_SUBSCR

    • 实现TOS1[TOS] = TOS2
  • DELETE_SUBSCR

    • 实现del TOS1[TOS]

Coroutine opcodes

  • GET_AWAITABLE
    • 实现TOS = get_awaitable(TOS),如果o是协程对象或带有 CO_ITERABLE_COROUTINE 标志的生成器对象,则get_awaitable(o)返回o,或者解析o.__await__

3.5 版中的新Function。

  • GET_AITER
    • 实现TOS = TOS.__aiter__()

3.5 版中的新Function。

在版本 3.7 中进行了更改:不再支持从__aiter__返回 await 对象。

  • GET_ANEXT
    • 实现PUSH(get_awaitable(TOS.__anext__()))。有关get_awaitable的详细信息,请参见GET_AWAITABLE

3.5 版中的新Function。

  • END_ASYNC_FOR
    • 终止async for循环。处理 await 下一个项目时引发的异常。如果 TOS 为StopAsyncIteration,则从堆栈中弹出 7 个值,并使用后三个值恢复异常状态。否则,使用堆栈中的三个值重新引发异常。从块堆栈中删除了异常处理程序块。

3.8 版的新Function。

  • BEFORE_ASYNC_WITH
    • 从堆栈顶部的对象解析__aenter____aexit__。将__aexit____aenter__()的结果压入堆栈。

3.5 版中的新Function。

  • SETUP_ASYNC_WITH
    • 创建一个新的框架对象。

3.5 版中的新Function。

Miscellaneous opcodes

  • PRINT_EXPR

    • 为交互模式实现表达式语句。从堆栈中删除 TOS 并进行打印。在非交互模式下,表达式语句以POP_TOP终止。
  • SET_ADD(* i *)

    • 拨打set.add(TOS1[-i], TOS)。用于实现集合理解。
  • LIST_APPEND(* i *)

    • 拨打list.append(TOS[-i], TOS)。用于实现列表推导。
  • MAP_ADD(* i *)

    • 拨打dict.__setitem__(TOS1[-i], TOS1, TOS)。用于实施 dict 理解。

3.1 版中的新Function。

在 3.8 版中更改:Map 值为 TOS,Map 键为 TOS1.以前,这些都是相反的。

对于所有SET_ADDLIST_APPENDMAP_ADD指令,当弹出添加的值或键/值对时,容器对象仍保留在堆栈上,因此可用于循环的进一步迭代。

  • RETURN_VALUE

    • 与 TOS 一起返回给函数的调用者。
  • YIELD_VALUE

  • YIELD_FROM

    • 弹出 TOS 并从generator作为子迭代器委派给它。

版本 3.3 中的新Function。

  • SETUP_ANNOTATIONS
    • 检查locals()中是否定义了__annotations__,如果没有定义则设置为空的dict。仅当类或模块主体静态包含variable annotations时,才会发出此操作码。

3.6 版的新Function。

  • IMPORT_STAR

    • 将所有不以'_'开头的符号直接从模块 TOS 加载到本地名称空间。加载所有名称后,将弹出该模块。此操作码实现from module import *
  • POP_BLOCK

    • 从块堆栈中删除一个块。每帧有一堆块,表示try语句,等等。
  • POP_EXCEPT

    • 从块堆栈中删除一个块。弹出的块必须是异常处理程序块,该异常处理程序块是在进入 except 处理程序时隐式创建的。除了从帧堆栈中弹出无关的值外,最后三个弹出的值还用于恢复异常状态。
  • POP_FINALLY(* preserve_tos *)

    • 清理值堆栈和块堆栈。如果* preserve_tos *不是0,则在执行其他堆栈操作后,首先将 TOS 从堆栈中弹出并推入堆栈:
  • 如果 TOS 是NULL或整数(由BEGIN_FINALLYCALL_FINALLY推),则会从堆栈中弹出。

  • 如果 TOS 是一个异常类型(引发异常时按下),则从堆栈中弹出 6 个值,最后三个弹出的值用于恢复异常状态。从块堆栈中删除了异常处理程序块。

它类似于END_FINALLY,但不更改字节码计数器也不引发异常。用于在finally块中实现breakcontinuereturn

3.8 版的新Function。

3.8 版的新Function。

  • END_FINALLY

    • 终止finally子句。解释器回忆根据 TOS 的值,是否必须重新引发异常或必须 continue 执行异常。
  • 如果 TOS 为NULL(由BEGIN_FINALLY推动),则从下一条指令 continue。 TOS 弹出。

  • 如果 TOS 是整数(由CALL_FINALLY推),则将字节码计数器设置为 TOS。 TOS 弹出。

  • 如果 TOS 是一个异常类型(引发异常时将被按下),则从堆栈中弹出 6 个值,前三个弹出的值用于重新引发异常,后三个弹出的值用于恢复异常状态。从块堆栈中删除了异常处理程序块。

  • LOAD_BUILD_CLASS

    • builtins.__build_class__()压入堆栈。以后由CALL_FUNCTION调用以构造一个类。
  • SETUP_WITH(* delta *)

    • 此操作码在 with 块开始之前执行若干操作。首先,它从上下文 Management 器中加载exit()并将其推入堆栈,以供WITH_CLEANUP_START以后使用。然后,调用enter(),并压入指向* delta *的 finally 块。最后,调用__enter__()方法的结果被压入堆栈。下一个操作码将忽略它(POP_TOP),或将其存储在一个或多个变量中(STORE_FASTSTORE_NAMEUNPACK_SEQUENCE)。

3.2 版中的新Function。

  • WITH_CLEANUP_START
    • with语句块退出时,开始清理堆栈。

如果在 with 块中引发了异常,则堆栈的顶部是NULL(由BEGIN_FINALLY推动)或 6 个值。下面是上下文 Management 器的exit()aexit()绑定方法。

如果 TOS 为NULL,则调用SECOND(None, None, None),从堆栈中删除该函数,保留 TOS,然后将None推入堆栈。否则调用SEVENTH(TOP, SECOND, THIRD),向下移动堆栈的底部 3 个值,将空点替换为NULL并压入 TOS。最后推送呼叫结果。

  • WITH_CLEANUP_FINISH
    • with语句块退出时,完成清理堆栈的操作。

TOS 是WITH_CLEANUP_START推动的__exit__()__aexit__()函数调用的结果。 SECOND 是None或异常类型(引发异常时按下)。

从堆栈中弹出两个值。如果 SECOND 不为 None 并且 TOS 为 true,则展开 EXCEPT_HANDLER 块,该块是在捕获异常时创建的,并将NULL压入堆栈。

以下所有操作码均使用其参数。

  • STORE_NAME(* namei *)

    • 实现name = TOS。 * namei name *在代码对象的属性co_names中的索引。如果可能,编译器将try使用STORE_FASTSTORE_GLOBAL
  • DELETE_NAME(* namei *)

    • 实现del name,其中* namei *是代码对象的co_names属性的索引。
  • UNPACK_SEQUENCE(* count *)

    • 将 TOS 打包成* count *个单独的值,这些值从右到左放入堆栈中。
  • UNPACK_EX(计数)

    • 实现带有加星标目标的分配:将 TOS 中的可迭代项解压缩为单个值,其中值的总数可以小于可迭代项中的项数:新值之一将是所有剩余项的列表。
  • counts 的低字节是列表值之前的值的数量, counts *的高字节是列表值之后的值的数量。结果值从右到左放入堆栈。
  • STORE_ATTR(* namei *)

    • 实现TOS.name = TOS1,其中* namei *是co_names中 name 的索引。
  • DELETE_ATTR(* namei *)

    • 使用* namei *作为co_names的索引来实现del TOS.name
  • STORE_GLOBAL(* namei *)

    • 用作STORE_NAME,但将名称存储为全局名称。
  • DELETE_GLOBAL(* namei *)

  • LOAD_CONST(* consti *)

    • co_consts[consti]压入堆栈。
  • LOAD_NAME(* namei *)

    • 将与co_names[namei]关联的值压入堆栈。
  • BUILD_TUPLE(* count *)

    • 创建一个从堆栈中消耗* count *个项目的 Tuples,并将生成的 Tuples 推入堆栈。
  • BUILD_LIST(* count *)

  • BUILD_SET(* count *)

  • BUILD_MAP(* count *)

    • 将新的字典对象压入堆栈。弹出2 * count个项目,以便词典包含* count *个条目:{..., TOS3: TOS2, TOS1: TOS}

在版本 3.5 中进行了更改:字典是从堆栈项目创建的,而不是创建一个预先设置大小以容纳* count *个项目的空字典。

  • BUILD_CONST_KEY_MAP(* count *)
    • BUILD_MAP专门用于常量键的版本。弹出堆栈中包含键 Tuples 的顶部元素,然后从TOS1开始,弹出* count *值以形成内置字典中的值。

3.6 版的新Function。

  • BUILD_STRING(* count *)
    • 连接来自堆栈的* count *字符串,并将结果字符串推入堆栈。

3.6 版的新Function。

  • BUILD_TUPLE_UNPACK(* count *)
    • 从堆栈中弹出* count *可迭代对象,将它们合并为一个 Tuples,然后推送结果。在 Tuples 显示(*x, *y, *z)中实现可迭代的拆包。

3.5 版中的新Function。

  • BUILD_TUPLE_UNPACK_WITH_CALL(* count *)
    • 这类似于BUILD_TUPLE_UNPACK,但用于f(*x, *y, *z)调用语法。位置count + 1处的堆栈项应为对应的可调用f

3.6 版的新Function。

  • BUILD_LIST_UNPACK(* count *)
    • 这类似于BUILD_TUPLE_UNPACK,但是推送列表而不是 Tuples。在列表显示[*x, *y, *z]中实现可迭代的拆包。

3.5 版中的新Function。

  • BUILD_SET_UNPACK(* count *)
    • 这类似于BUILD_TUPLE_UNPACK,但推送一个集合而不是 Tuples。在集合显示{*x, *y, *z}中实现可迭代的拆包。

3.5 版中的新Function。

  • BUILD_MAP_UNPACK(* count *)
    • 从堆栈中弹出* count *Map,将它们合并为一个字典,然后推送结果。在字典显示{**x, **y, **z}中实现字典解压缩。

3.5 版中的新Function。

  • BUILD_MAP_UNPACK_WITH_CALL(* count *)
    • 这类似于BUILD_MAP_UNPACK,但用于f(**x, **y, **z)调用语法。位置count + 2处的堆栈项应为对应的可调用f

3.5 版中的新Function。

在版本 3.6 中更改:可调用对象的位置是pass在操作码参数中添加 2 而不是在参数的第二个字节中对其进行编码来确定的。

  • LOAD_ATTR(* namei *)

    • getattr(TOS, co_names[namei])代替 TOS。
  • COMPARE_OP(* opname *)

    • 执行布尔运算。可以在cmp_op[opname]中找到操作名称。
  • IMPORT_NAME(* namei *)

    • 导入模块co_names[namei]。弹出 TOS 和 TOS1 并提供import()的* fromlist level *参数。模块对象被压入堆栈。当前的名称空间不受影响:对于正确的 import 语句,随后的STORE_FAST指令将修改该名称空间。
  • IMPORT_FROM(* namei *)

    • 从 TOS 中找到的模块中加载属性co_names[namei]。生成的对象被压入堆栈,随后由STORE_FAST指令存储。
  • JUMP_FORWARD(* delta *)

    • 将字节码计数器增加* delta *。
  • POP_JUMP_IF_TRUE(* target *)

    • 如果 TOS 为 true,则将字节码计数器设置为* target *。 TOS 弹出。

3.1 版中的新Function。

  • POP_JUMP_IF_FALSE(* target *)
    • 如果 TOS 为 false,则将字节码计数器设置为* target *。 TOS 弹出。

3.1 版中的新Function。

  • JUMP_IF_TRUE_OR_POP(* target *)
    • 如果 TOS 为 true,则将字节码计数器设置为* target *并将 TOS 留在堆栈中。否则(TOS 为假),将弹出 TOS。

3.1 版中的新Function。

  • JUMP_IF_FALSE_OR_POP(* target *)
    • 如果 TOS 为 false,则将字节码计数器设置为* target *并将 TOS 留在堆栈中。否则(TOS 为 true),将弹出 TOS。

3.1 版中的新Function。

  • JUMP_ABSOLUTE(* target *)

    • 将字节码计数器设置为* target *。
  • FOR_ITER(* delta *)

    • TOS 是iterator。调用其next()方法。如果产生一个新值,则将其压入堆栈(将迭代器保留在其下方)。如果迭代器指示已用尽,则弹出 TOS,并且字节码计数器增加* delta *。
  • LOAD_GLOBAL(* namei *)

    • 将名为co_names[namei]的全局变量加载到堆栈中。
  • SETUP_FINALLY(* delta *)

    • 将 try 块从 try-finally 或 try-except 子句推入块堆栈。 * delta *指向 finally 块或第一个除外块。
  • CALL_FINALLY(* delta *)

    • 将下一条指令的地址压入堆栈,并使字节码计数器增加* delta *。用于作为“子例程”调用 finally 块。

3.8 版的新Function。

  • LOAD_FAST(* var_num *)

    • 将对本地co_varnames[var_num]的引用压入堆栈。
  • STORE_FAST(* var_num *)

    • 将 TOS 存储到本地co_varnames[var_num]
  • DELETE_FAST(* var_num *)

    • 删除本地co_varnames[var_num]
  • LOAD_CLOSURE(* i *)

    • 将引用推入单元格的插槽* i 和可用变量存储中包含的单元格。如果 i 小于 co_cellvars *的长度,则变量的名称为co_cellvars[i]。否则为co_freevars[i - len(co_cellvars)]
  • LOAD_DEREF(* i *)

    • 加载包含在单元的插槽* i *和可用变量存储中的单元。将引用推送到单元格包含在堆栈中的对象。
  • LOAD_CLASSDEREF(* i *)

    • 就像LOAD_DEREF一样,但是在查询单元之前先检查 locals 字典。这用于在类主体中加载自由变量。

3.4 版的新Function。

  • STORE_DEREF(* i *)

    • 将 TOS 存储到单元的插槽* i *中包含的单元中,并释放变量存储。
  • DELETE_DEREF(* i *)

    • 清空包含在单元格* i *中的单元格和可用变量存储。由del语句使用。

3.2 版中的新Function。

  • RAISE_VARARGS(* argc *)

    • 使用raise语句的 3 种形式之一引发异常,具体取决于* argc *的值:
  • 0:raise(重新提出以前的 exception)

  • 1:raise TOS(引发异常实例或在TOS处键入)

  • 2:raise TOS1 from TOS(引发异常实例或在TOS1上将__cause__设置为TOS键入)

  • CALL_FUNCTION(* argc *)

    • 用位置参数调用可调用对象。 * argc *表示位置参数的数量。堆栈的顶部包含位置参数,最右边的参数在顶部。参数下方是要调用的可调用对象。 CALL_FUNCTION将所有参数和可调用对象弹出堆栈,使用这些参数调用可调用对象,然后推入可调用对象返回的返回值。

在版本 3.6 中更改:此操作码仅用于带有位置参数的调用。

  • CALL_FUNCTION_KW(* argc *)
    • 调用带有位置(如果有)和关键字参数的可调用对象。 * argc *表示位置和关键字参数的总数。堆栈的顶部元素包含关键字参数名称的 Tuples。在其下是按与 Tuples 相对应的 Sequences 的关键字参数。下面是位置参数,最右边的参数在顶部。参数下方是要调用的可调用对象。 CALL_FUNCTION_KW将所有参数和可调用对象弹出堆栈,使用这些参数调用可调用对象,然后推入可调用对象返回的返回值。

在版本 3.6 中更改:关键字参数以 Tuples 而不是字典的形式打包,* argc *表示参数的总数。

  • CALL_FUNCTION_EX(* flags *)
    • 用位置和关键字参数的可变集调用可调用对象。如果设置了* flags *的最低位,则堆栈的顶部将包含一个包含附加关键字参数的 Map 对象。在其下是一个可迭代的对象,其中包含位置参数和要调用的可调用对象。 BUILD_MAP_UNPACK_WITH_CALLBUILD_TUPLE_UNPACK_WITH_CALL可用于合并多个包含参数的 Map 对象和可迭代对象。在调用 callable 之前,分别对 Map 对象和可迭代对象进行“拆包”,并将其内容分别作为关键字和位置参数传递。 CALL_FUNCTION_EX将所有参数和可调用对象弹出堆栈,使用这些参数调用可调用对象,并推入可调用对象返回的返回值。

3.6 版的新Function。

  • LOAD_METHOD(* namei *)
    • 从 TOS 对象中加载名为co_names[namei]的方法。 TOS 弹出。此字节码区分两种情况:如果 TOS 具有名称正确的方法,则字节码将推送未绑定的方法和 TOS。调用未绑定方法时,CALL_METHOD将 TOS 用作第一个参数(self)。否则,将推送NULL和pass属性查找返回的对象。

3.7 版中的新Function。

  • CALL_METHOD(* argc *)
    • 调用方法。 * argc *是位置参数的数量。不支持关键字参数。该操作码设计用于LOAD_METHOD。位置参数位于堆栈的顶部。在它们下面,在LOAD_METHOD中描述的两个项目在堆栈上(self和一个未绑定的方法对象,或者NULL和一个任意可调用的对象)。它们全部弹出,并返回返回值。

3.7 版中的新Function。

  • MAKE_FUNCTION(* flags *)

    • 将新的Function对象压入堆栈。从下到上,如果参数携带指定的标志值,则消耗的堆栈必须包含值
  • 0x01按位置 Sequences 排列的仅位置参数和位置或关键字参数的默认值的 Tuples

  • 0x02仅关键字参数默认值的字典

  • 0x04Comments 词典

  • 0x08一个包含用于自由变量的单元格的 Tuples,从而进行关闭

  • 与Function关联的代码(在 TOS1 处)

  • 函数的qualified name(在 TOS 处)

  • BUILD_SLICE(* argc *)

    • 将切片对象压入堆栈。 * argc *必须为 2 或 3.如果为 2,则推入slice(TOS1, TOS);如果为 3,则推slice(TOS2, TOS1, TOS)。有关更多信息,请参见slice()内置函数。
  • EXTENDED_ARG(* ext *)

    • 在操作码前加一个太大的参数以至于不能容纳默认的一个字节的前缀。 * ext *保留一个额外的字节,该字节充当参数中的高位。对于每个操作码,最多允许三个前缀EXTENDED_ARG,形成从两个字节到四个字节的参数。
  • FORMAT_VALUE(* flags *)

    • 用于实现格式化的 Literals 字符串(f 字符串)。从堆栈中弹出一个可选的* fmt_spec ,然后是一个必需的 value *。 * flags 的解释如下:
  • (flags & 0x03) == 0x00:* value *的格式保持不变。

  • (flags & 0x03) == 0x01:对* value *调用str(),然后再对其进行格式化。

  • (flags & 0x03) == 0x02:对* value *调用repr(),然后再对其进行格式化。

  • (flags & 0x03) == 0x03:对* value *调用ascii(),然后再对其进行格式化。

  • (flags & 0x04) == 0x04:从堆栈中弹出* fmt_spec 并使用它,否则使用一个空的 fmt_spec *。

使用PyObject_Format()进行格式化。结果被压入堆栈。

3.6 版的新Function。

  • HAVE_ARGUMENT
    • 这不是 true 的操作码。它标识了不使用其参数的操作码与不使用其参数的操作码之间的分界线(分别为< HAVE_ARGUMENT>= HAVE_ARGUMENT)。

在版本 3.6 中进行了更改:现在每个指令都有一个参数,但是操作码< HAVE_ARGUMENT忽略它。以前,只有操作码>= HAVE_ARGUMENT带有参数。

Opcode collections

提供这些集合是为了自动反省字节码指令:

  • dis. opname

    • 操作名称序列,可使用字节码索引。
  • dis. opmap

    • 字典将操作名称 Map 到字节码。
  • dis. cmp_op

    • 所有比较操作名称的 Sequences。
  • dis. hasconst

    • 访问常量的字节码序列。
  • dis. hasfree

    • 访问自由变量的字节码序列(请注意,在此上下文中,“ free”是指内部作用域引用的当前作用域中的名称或从该作用域引用的外部作用域中的名称.它不包括对以下内容的引用)全局或内置作用域)。
  • dis. hasname

    • 按名称访问属性的字节码序列。
  • dis. hasjrel

    • 具有相对跳转目标的字节码序列。
  • dis. hasjabs

    • 具有绝对跳转目标的字节码序列。
  • dis. haslocal

    • 访问局部变量的字节码序列。
  • dis. hascompare

    • 布尔运算的字节码序列。