"dis" --- Python 字节码反汇编器
*******************************

**源代码:** Lib/dis.py

======================================================================

"dis" 模块通过反汇编支持CPython的 *bytecode* 分析。该模块作为输入的
CPython 字节码在文件 "Include/opcode.h" 中定义，并由编译器和解释器使用
。

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

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

在 3.10 版更改: 跳转、异常处理和循环指令的参数现在将为指令偏移量而不是
字节偏移量。

示例：给出函数 "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" 是行号)。


字节码分析
==========

3.4 新版功能.

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

class dis.Bytecode(x, *, first_line=None, current_offset=None)

   分析的字节码对应于函数、生成器、异步生成器、协程、方法、源代码字符
   串或代码对象（由 "compile()" 返回）。

   这是下面列出的许多函数的便利包装，最值得注意的是
   "get_instructions()" ，迭代于 "Bytecode" 的实例产生字节码操作
   "Instruction" 的实例。

   如果 *first_line* 不是 "None" ，则表示应该为反汇编代码中的第一个源
   代码行报告的行号。否则，源行信息（如果有的话）直接来自反汇编的代码
   对象。

   如果 *current_offset* 不是 "None" ，它指的就是汇编代码中的指令偏移
   量。设置它意味着 "dis()" 将针对指定的操作码显示“当前指令”标记。

   classmethod from_traceback(tb)

      从给定回溯构造一个 "Bytecode" 实例，将设置 *current_offset* 为异
      常负责的指令。

   codeobj

      已编译的代码对象。

   first_line

      代码对象的第一个源代码行（如果可用）

   dis()

      返回字节码操作的格式化视图（与 "dis.dis()" 打印相同，但作为多行
      字符串返回）。

   info()

      返回带有关于代码对象的详细信息的格式化多行字符串，如
      "code_info()" 。

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

示例:

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


分析函数
========

"dis" 模块还定义了以下分析函数，它们将输入直接转换为所需的输出。如果只
执行单个操作，它们可能很有用，因此中间分析对象没用：

dis.code_info(x)

   返回格式化的多行字符串，其包含详细代码对象信息的用于被提供的函数、
   生成器、异步生成器、协程、方法、源代码字符串或代码对象。

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

   3.2 新版功能.

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

dis.show_code(x, *, file=None)

   将提供的函数、方法。源代码字符串或代码对象的详细代码对象信息打印到
   *file* （如果未指定 *file* ，则为 "sys.stdout" ）。

   这是 "print(code_info(x), file=file)" 的便捷简写，用于在解释器提示
   符下进行交互式探索。

   3.2 新版功能.

   在 3.4 版更改: 添加 *file* 形参。

dis.dis(x=None, *, file=None, depth=None)

   反汇编 *x* 对象。 *x* 可以表示模块、类、方法、函数、生成器、异步生
   成器、协程、代码对象、源代码字符串或原始字节码的字节序列。对于模块
   ，它会反汇编所有功能。对于一个类，它反汇编所有方法（包括类和静态方
   法）。对于代码对象或原始字节码序列，它每字节码指令打印一行。它还递
   归地反汇编嵌套代码对象（推导式代码，生成器表达式和嵌套函数，以及用
   于构建嵌套类的代码）。在被反汇编之前，首先使用 "compile()" 内置函数
   将字符串编译为代码对象。如果未提供任何对象，则此函数会反汇编最后一
   次回溯。

   如果提供的话，反汇编将作为文本写入提供的 *file* 参数，否则写入
   "sys.stdout" 。

   递归的最大深度受 *depth* 限制，除非它是 "None" 。 "depth=0" 表示没
   有递归。

   在 3.4 版更改: 添加 *file* 形参。

   在 3.7 版更改: 实现了递归反汇编并添加了 *depth* 参数。

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

dis.distb(tb=None, *, file=None)

   如果没有传递，则使用最后一个回溯来反汇编回溯的堆栈顶部函数。 指示了
   导致异常的指令。

   如果提供的话，反汇编将作为文本写入提供的 *file* 参数，否则写入
   "sys.stdout" 。

   在 3.4 版更改: 添加 *file* 形参。

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

   反汇编代码对象，如果提供了 *lasti* ，则指示最后一条指令。输出分为以
   下几列：

   1. 行号，用于每行的第一条指令

   2. 当前指令，表示为 "-->" ，

   3. 一个标记的指令，用 ">>" 表示，

   4. 指令的地址，

   5. 操作码名称，

   6. 操作参数，和

   7. 括号中参数的解释。

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

   如果提供的话，反汇编将作为文本写入提供的 *file* 参数，否则写入
   "sys.stdout" 。

   在 3.4 版更改: 添加 *file* 形参。

dis.get_instructions(x, *, first_line=None)

   在所提供的函数、方法、源代码字符串或代码对象中的指令上返回一个迭代
   器。

   迭代器生成一系列 "Instruction" ，命名为元组，提供所提供代码中每个操
   作的详细信息。

   如果 *first_line* 不是 "None" ，则表示应该为反汇编代码中的第一个源
   代码行报告的行号。否则，源行信息（如果有的话）直接来自反汇编的代码
   对象。

   3.4 新版功能.

dis.findlinestarts(code)

   这个生成器函数使用代码对象 *code* 的 "co_lines" 方法来查找源代码中
   行开头的偏移量。 它们将作为 "(offset, lineno)" 对被生成。

   在 3.6 版更改: 行号可能会减少。 以前，他们总是在增加。

   在 3.10 版更改: 使用 **PEP 626** "co_lines" 方法而不是代码对象的
   "co_firstlineno" 和 "co_lnotab" 属性。

dis.findlabels(code)

   检测作为跳转目标的原始编译后字节码字符串 *code* 中的所有偏移量，并
   返回这些偏移量的列表。

dis.stack_effect(opcode, oparg=None, *, jump=None)

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

   如果代码有一个跳转目标并且 *jump* 是 "True" ，则 "drag_effect()" 将
   返回跳转的堆栈效果。如果 *jump* 是 "False" ，它将返回不跳跃的堆栈效
   果。如果 *jump* 是 "None" （默认值），它将返回两种情况的最大堆栈效
   果。

   3.4 新版功能.

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


Python字节码说明
================

"get_instructions()" 函数和 "Bytecode" 类提供字节码指令的详细信息的
"Instruction" 实例：

class dis.Instruction

   字节码操作的详细信息

   opcode

      操作的数字代码，对应于下面列出的操作码值和 操作码集合 中的字节码
      值。

   opname

      人类可读的操作名称

   arg

      操作的数字参数（如果有的话），否则为 "None"

   argval

      已解析的 arg 值（如果已知），否则与 arg 相同

   argrepr

      人类可读的操作参数描述

   offset

      在字节码序列中的起始操作索引

   starts_line

      行由此操作码（如果有）启动，否则为 "None"

   is_jump_target

      如果其他代码跳到这里，则为 "True" ，否则为 "False"

   3.4 新版功能.

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

**一般指令**

NOP

   什么都不做。 用作字节码优化器的占位符。

POP_TOP

   删除堆栈顶部（TOS）项。

ROT_TWO

   交换两个最顶层的堆栈项。

ROT_THREE

   将第二个和第三个堆栈项向上提升一个位置，顶项移动到位置三。

ROT_FOUR

   将第二个、第三个和第四个堆栈项向上提升一个位置，将顶项移动到第四个
   位置。

   3.8 新版功能.

DUP_TOP

   复制堆栈顶部的引用。

   3.2 新版功能.

DUP_TOP_TWO

   复制堆栈顶部的两个引用，使它们保持相同的顺序。

   3.2 新版功能.

**一元操作**

一元操作获取堆栈顶部元素，应用操作，并将结果推回堆栈。

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

   如果 "TOS" 是一个 *generator iterator* 或 *coroutine* 对象则保持原
   样。否则实现 "TOS = iter(TOS)" 。

   3.5 新版功能.

**二元操作**

二元操作从堆栈中删除堆栈顶部（TOS）和第二个最顶层堆栈项（TOS1）。 它们
执行操作，并将结果放回堆栈。

BINARY_POWER

   实现 "TOS = TOS1 ** TOS" 。

BINARY_MULTIPLY

   实现 "TOS = TOS1 * TOS" 。

BINARY_MATRIX_MULTIPLY

   实现 "TOS = TOS1 @ TOS" 。

   3.5 新版功能.

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" 。

**就地操作**

就地操作就像二元操作，因为它们删除了TOS和TOS1，并将结果推回到堆栈上，
但是当TOS1支持它时，操作就地完成，并且产生的TOS可能是（但不一定） 原来
的TOS1。

INPLACE_POWER

   就地实现 "TOS = TOS1 ** TOS" 。

INPLACE_MULTIPLY

   就地实现 "TOS = TOS1 * TOS" 。

INPLACE_MATRIX_MULTIPLY

   就地实现 "TOS = TOS1 @ TOS" 。

   3.5 新版功能.

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]" 。

**协程操作码**

GET_AWAITABLE

   实现 "TOS = get_awaitable(TOS)" ，其中 "get_awaitable(o)" 返回 "o"
   如果 "o" 是一个有 CO_ITERABLE_COROUTINE 标志的协程对象或生成器对象
   ，否则解析 "o.__await__" 。

   3.5 新版功能.

GET_AITER

   实现 "TOS = TOS.__aiter__()" 。

   3.5 新版功能.

   在 3.7 版更改: 已经不再支持从 "__aiter__" 返回可等待对象。

GET_ANEXT

   将 "get_awaitable(TOS.__anext__())" 推入栈。 请参阅 "GET_AWAITABLE"
   了解有关 "get_awaitable" 的详情。

   3.5 新版功能.

END_ASYNC_FOR

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

   3.8 新版功能.

BEFORE_ASYNC_WITH

   从栈顶对象解析 "__aenter__" 和 "__aexit__" 。将 "__aexit__" 和
   "__aenter__()" 的结果推入堆栈。

   3.5 新版功能.

SETUP_ASYNC_WITH

   创建一个新的帧对象。

   3.5 新版功能.

**其他操作码**

PRINT_EXPR

   实现交互模式的表达式语句。TOS从堆栈中被移除并打印。在非交互模式下，
   表达式语句以 "POP_TOP" 终止。

SET_ADD(i)

   调用 "set.add(TOS1[-i], TOS)" 。 用于实现集合推导。

LIST_APPEND(i)

   调用 "list.append(TOS1[-i], TOS)"。 用于实现列表推导式。

MAP_ADD(i)

   调用 "dict.__setitem__(TOS1[-i], TOS1, TOS)" 。 用于实现字典推导。

   3.1 新版功能.

   在 3.8 版更改: 映射值为 TOS ，映射键为 TOS1 。之前，它们被颠倒了。

对于所有 "SET_ADD" 、 "LIST_APPEND" 和 "MAP_ADD" 指令，当弹出添加的值
或键值对时，容器对象保留在堆栈上，以便它可用于循环的进一步迭代。

RETURN_VALUE

   返回 TOS 到函数的调用者。

YIELD_VALUE

   弹出 TOS 并从一个 *generator* 生成它。

YIELD_FROM

   弹出 TOS 并将其委托给它作为 *generator* 的子迭代器。

   3.3 新版功能.

SETUP_ANNOTATIONS

   检查 "__annotations__" 是否在 "locals()" 中定义，如果没有，它被设置
   为空 "dict" 。只有在类或模块体静态地包含 *variable annotations* 时
   才会发出此操作码。

   3.6 新版功能.

IMPORT_STAR

   将所有不以 "'_'" 开头的符号直接从模块 TOS 加载到局部命名空间。加载
   所有名称后弹出该模块。这个操作码实现了 "from module import *" 。

POP_BLOCK

   从块堆栈中删除一个块。有一块堆栈，每帧用于表示 "try" 语句等。

POP_EXCEPT

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

RERAISE

   重新引发当前位于栈顶的异常。 如果 oparg 为非零值，则将当前帧的
   "f_lasti" 恢复为异常被引发时的值。

   3.9 新版功能.

WITH_EXCEPT_START

   调用堆栈中 7 号位置上的函数并附带栈顶位置的三项作为参数。 用来在
   "with" 语句内发生异常时实现调用
   "context_manager.__exit__(*exc_info())"。

   3.9 新版功能.

LOAD_ASSERTION_ERROR

   将 "AssertionError" 推入栈顶。 由 "assert" 语句使用。

   3.9 新版功能.

LOAD_BUILD_CLASS

   将 "builtins .__ build_class__()" 推到堆栈上。它之后被
   "CALL_FUNCTION" 调用来构造一个类。

SETUP_WITH(delta)

   此操作码会在 with 代码块开始之前执行多个操作。 首先，它从上下文管理
   器加载 "__exit__()" 并将其推入栈顶以供 "WITH_EXCEPT_START" 后续使用
   。 然后，调用 "__enter__()"，并推入一个指向 *delta* 的 finally 代码
   块。 最后，将调用 "__enter__()" 方法的结果推入栈顶。 下一个操作码将
   忽略它 ("POP_TOP")，或将其存储在一个或多个变量 ("STORE_FAST",
   "STORE_NAME" 或 "UNPACK_SEQUENCE") 中。

   3.2 新版功能.

COPY_DICT_WITHOUT_KEYS

   TOS 是一个映射键的元组，而 TOS1 是匹配目标。 将 TOS 替换为由 TOS1
   条目组成的 "dict"，但不包含任何 TOS 中的键。

   3.10 新版功能.

GET_LEN

   将 "len(TOS)" 推入栈顶。

   3.10 新版功能.

MATCH_MAPPING

   如果 TOS 是 "collections.abc.Mapping" 的实例（或者更准确地说：如果
   在它的 "tp_flags" 中设置了 "Py_TPFLAGS_MAPPING" 旗标），则将 "True"
   推入栈顶。 否则，推入 "False"。

   3.10 新版功能.

MATCH_SEQUENCE

   如果 TOS 是 "collections.abc.Sequence" 的实例而 *不是*
   "str"/"bytes"/"bytearray" 的实例（或者更准确地说：如果在它的
   "tp_flags" 中设置了 "Py_TPFLAGS_SEQUENCE" 旗标），则将 "True" 推入
   栈顶。 否则 ，推入 "False"。

   3.10 新版功能.

MATCH_KEYS

   TOS 是一个映射键的元组，而 TOS1 是匹配目标。 如果 TOS1 包含 TOS 中
   的所有键，则推入一个包含对应值的 "tuple"，再推入 "True"。 否则，推
   入 "None"，再推入 "False"。

   3.10 新版功能.

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

STORE_NAME(namei)

   实现 "name = TOS"。 *namei* 是 *name* 在代码对象的 "co_names" 属性
   中的索引。 在可能的情况下，编译器会尝试使用 "STORE_FAST" 或
   "STORE_GLOBAL"。

DELETE_NAME(namei)

   实现 "del name" ，其中 *namei* 是代码对象的 "co_names" 属性的索引。

UNPACK_SEQUENCE(count)

   将 TOS 解包为 *count* 个单独的值，它们将按从右至左的顺序被放入堆栈
   。

UNPACK_EX(counts)

   实现使用带星号的目标进行赋值：将 TOS 中的可迭代对象解包为单独的值，
   其中值的总数可以小于可迭代对象中的项数：新值之一将是由所有剩余项构
   成的列表。

   *counts* 的低字节是列表值之前的值的数量，*counts* 中的高字节则是之
   后的值的数量。 结果值会按从右至左的顺序入栈。

STORE_ATTR(namei)

   实现 "TOS.name = TOS1"，其中 *namei* 是 name 在 "co_names" 中的索引
   号。

DELETE_ATTR(namei)

   实现 "del TOS.name"，使用 *namei* 作为 "co_names" 中的索引号。

STORE_GLOBAL(namei)

   类似于 "STORE_NAME" 但会将 name 存储为全局变量。

DELETE_GLOBAL(namei)

   类似于 "DELETE_NAME" 但会删除一个全局变量。

LOAD_CONST(consti)

   将 "co_consts[consti]" 推入栈顶。

LOAD_NAME(namei)

   将与 "co_names[namei]" 相关联的值推入栈顶。

BUILD_TUPLE(count)

   创建一个使用了来自栈的 *count* 个项的元组，并将结果元组推入栈顶。

BUILD_LIST(count)

   类似于 "BUILD_TUPLE" 但会创建一个列表。

BUILD_SET(count)

   类似于 "BUILD_TUPLE" 但会创建一个集合。

BUILD_MAP(count)

   将一个新字典对象推入栈顶。 弹出 "2 * count" 项使得字典包含 *count*
   个条目: "{..., TOS3: TOS2, TOS1: TOS}"。

   在 3.5 版更改: 字典是根据栈中的项创建而不是创建一个预设大小包含
   *count* 项的空字典。

BUILD_CONST_KEY_MAP(count)

   "BUILD_MAP" 版本专用于常量键。 弹出的栈顶元素包含一个由键构成的元组
   ，然后从 "TOS1" 开始从构建字典的值中弹出 *count* 个值。

   3.6 新版功能.

BUILD_STRING(count)

   拼接 *count* 个来自栈的字符串并将结果字符串推入栈顶。

   3.6 新版功能.

LIST_TO_TUPLE

   从堆栈中弹出一个列表并推入一个包含相同值的元组。

   3.9 新版功能.

LIST_EXTEND(i)

   调用 "list.extend(TOS1[-i], TOS)"。 用于构建列表。

   3.9 新版功能.

SET_UPDATE(i)

   调用 "set.update(TOS1[-i], TOS)"。 用于构建集合。

   3.9 新版功能.

DICT_UPDATE(i)

   调用 "dict.update(TOS1[-i], TOS)"。 用于构建字典。

   3.9 新版功能.

DICT_MERGE

   类似于 "DICT_UPDATE" 但对于重复的键会引发异常。

   3.9 新版功能.

LOAD_ATTR(namei)

   将 TOS 替换为 "getattr(TOS, co_names[namei])"。

COMPARE_OP(opname)

   执行布尔运算操作。 操作名称可在 "cmp_op[opname]" 中找到。

IS_OP(invert)

   执行 "is" 比较，或者如果 "invert" 为 1 则执行 "is not"。

   3.9 新版功能.

CONTAINS_OP(invert)

   执行 "in" 比较，或者如果 "invert" 为 1 则执行 "not in"。

   3.9 新版功能.

IMPORT_NAME(namei)

   导入模块 "co_names[namei]"。 会弹出 TOS 和 TOS1 以提供 *fromlist*
   和 *level* 参数给 "__import__()"。 模块对象会被推入栈顶。 当前命名
   空间不受影响：对于一条标准 import 语句，会执行后续的 "STORE_FAST"
   指令来修改命名空间。

IMPORT_FROM(namei)

   从在 TOS 内找到的模块中加载属性 "co_names[namei]"。 结果对象会被推
   入栈顶，以便由后续的 "STORE_FAST" 指令来保存。

JUMP_FORWARD(delta)

   将字节码计数器的值增加 *delta*。

POP_JUMP_IF_TRUE(target)

   如果 TOS 为真值，则将字节码计数器的值设为 *target*。 TOS 会被弹出。

   3.1 新版功能.

POP_JUMP_IF_FALSE(target)

   如果 TOS 为假值，则将字节码计数器的值设为 *target*。 TOS 会被弹出。

   3.1 新版功能.

JUMP_IF_NOT_EXC_MATCH(target)

   检测堆栈中的第二个值是否为匹配 TOS 的异常，如果不是则会跳转。 从堆
   栈中弹出两个值。

   3.9 新版功能.

JUMP_IF_TRUE_OR_POP(target)

   如果 TOS 为真值，则将字节码计数器的值设为 *target* 并将 TOS 留在栈
   顶。 否则（如 TOS 为假值），TOS 会被弹出。

   3.1 新版功能.

JUMP_IF_FALSE_OR_POP(target)

   如果 TOS 为假值，则将字节码计数器的值设为 *target* 并将 TOS 留在栈
   顶。 否则（如 TOS 为真值），TOS 会被弹出。

   3.1 新版功能.

JUMP_ABSOLUTE(target)

   将字节码计数器的值设为 *target*。

FOR_ITER(delta)

   TOS 是一个 *iterator*。 请调用其 "__next__()" 方法。 如果此操作产生
   了一个新值，则将其推入栈顶（将迭代器留在其下方）。 如果迭代器提示已
   耗尽，TOS 会被弹出，并且字节码计数器将增加 *delta*。

LOAD_GLOBAL(namei)

   加载名称为 "co_names[namei]" 的全局对象推入栈顶。

SETUP_FINALLY(delta)

   将一个来自 try-finally 或 try-except 子句的 try 代码块推入代码块栈
   顶。 相对 finally 代码块或第一个 except 代码块 *delta* 个点数。

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" 但在查询单元之前会首先检查局部对象字典。 这被用
   于加载类语句体中的自由变量。

   3.4 新版功能.

STORE_DEREF(i)

   将 TOS 存放到包含在单元的第 *i* 个空位中的单元内并释放可用存储空间
   。

DELETE_DEREF(i)

   清空包含在单元的第 *i* 个空位中的单元并释放可用存储空间。 被用于
   "del" 语句。

   3.2 新版功能.

RAISE_VARARGS(argc)

   使用 "raise" 语句的 3 种形式之一引发异常，具体形式取决于 *argc* 的
   值：

   * 0: "raise" (重新引发之前的异常)

   * 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*
   指明位置参数和关键字参数的总数量。 栈顶元素包含一个关键字参数名称的
   元组，名称必须为字符串。 在元组之下是与元组顺序相对应的关键字参数值
   。 在它之下则是位置参数，其中最右边的参数在最顶端。 在参数之下是要
   调用的可调用对象。 "CALL_FUNCTION_KW" 会从栈中弹出所有参数及可调用
   对象，附带这些参数调用该可调用对象，并将可调用对象所返回的返回值推
   入栈顶。

   在 3.6 版更改: 关键字参数会被打包为一个元组而非字典，*argc* 指明参
   数的总数量。

CALL_FUNCTION_EX(flags)

   调用一个可调用对象并附带位置参数和关键字参数变量集合。 如果设置了
   *flags* 的最低位，则栈顶包含一个由额外关键字参数组成的映射对象。 在
   调用该可调用对象之前，映射对象和可迭代对象会被分别“解包”并将它们的
   内容分别作为关键字参数和位置参数传入。 "CALL_FUNCTION_EX" 会中栈中
   弹出所有参数及可调用对象，附带这些参数调用该可调用对象，并将可调用
   对象所返回的返回值推入栈顶。

   3.6 新版功能.

LOAD_METHOD(namei)

   从 TOS 对象加载一个名为 "co_names[namei]" 的方法。 TOS 将被弹出。
   此字节码可区分两种情况：如果 TOS 有一个名称正确的方法，字节码会将未
   绑定方法和 TOS 推入栈顶。 TOS 将在调用未绑定方法时被用作
   "CALL_METHOD" 的第一个参数 ("self")。 否则会将 "NULL" 和属性查找所
   返回的对象推入栈顶。

   3.7 新版功能.

CALL_METHOD(argc)

   调用一个方法。 *argc* 是位置参数的数量。 关键字参数不受支持。 此操
   作码被设计用于配合 "LOAD_METHOD" 使用。 位置参数放在栈顶。 在它们之
   下放在栈中的是由 "LOAD_METHOD" 所描述的两个条目（或者是 "self" 和一
   个未绑定方法对象，或者是 "NULL" 和一个任意可调用对象）。 它们会被全
   部弹出并将返回值推入栈顶。

   3.7 新版功能.

MAKE_FUNCTION(flags)

   将一个新函数对象推入栈顶。 从底端到顶端，如果参数带有指定的旗标值则
   所使用的栈必须由这些值组成。

   * "0x01" 一个默认值的元组，用于按位置排序的仅限位置形参以及位置或关
     键字形参

   * "0x02" 一个仅限关键字形参的默认值的字典

   * "0x04" 一个包含形参标注的字符串元组。

   * "0x08" 一个包含用于自由变量的单元的元组，生成一个闭包

   * 与函数相关联的代码 (在 TOS1)

   * 函数的 *qualified name* (在 TOS)

   在 3.10 版更改: 旗标值 "0x04" 是一个字符串元组而非字典。

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)

   用于实现格式化字面值字符串（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 新版功能.

MATCH_CLASS(count)

   TOS 是一个包含关键字属性名称的元组，TOS1 是要匹配的类，而 TOS2 是匹
   配目标。 *count* 是位置子模式的数量。

   弹出 TOS。 如果 TOS2 是 TOS1 的一个实例且具有 *count* 和 TOS 所要求
   的位置和关键字属性，则将 TOS 设为 "True" 并将 TOS1 设为包含已提取属
   性的元组。 否则，将 TOS 设为 "False"。

   3.10 新版功能.

GEN_START(kind)

      弹出 TOS。 "kind" 操作数与生成器或协程的类型相对应。 合法的类型
      有代表生成器的 0，代表协程的 1，以及代表异步生成器的 2。

   3.10 新版功能.

ROT_N(count)

   将栈的前 *count* 项向上提升一个位置，并将 TOS 下移至位置 *count*。

   3.10 新版功能.

HAVE_ARGUMENT

   这不是一个真正的操作码。 它用于标明使用参数和不使用参数的操作码 (分
   别为 "< HAVE_ARGUMENT" 和 ">= HAVE_ARGUMENT") 之间的分隔线。

   在 3.6 版更改: 现在每条指令都带有参数，但操作码 "< HAVE_ARGUMENT"
   会忽略它。 之前仅限操作码 ">= HAVE_ARGUMENT" 带有参数。


操作码集合
==========

提供这些集合用于字节码指令的自动内省：

dis.opname

   操作名称的序列，可使用字节码来索引。

dis.opmap

   映射操作名称到字节码的字典

dis.cmp_op

   所有比较操作名称的序列。

dis.hasconst

   访问常量的字节码序列。

dis.hasfree

   访问自由变量的字节码序列（请注意这里所说的‘自由’是指在当前作用域中
   被内部作用域所引用的名称，或在外部作用域中被此作用域所引用的名称。
   它 *并不* 包括对全局或内置作用域的引用）。

dis.hasname

   按名称访问属性的字节码序列。

dis.hasjrel

   具有相对跳转目标的字节码序列。

dis.hasjabs

   具有绝对跳转目标的字节码序列。

dis.haslocal

   访问局部变量的字节码序列。

dis.hascompare

   布尔运算的字节码序列。
