32.12. "dis" --- Python bytecode的反組譯器
******************************************

**原始碼：**Lib/dis.py

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

"dis" 模組支援反組譯分析 CPython *bytecode*。CPython bytecode 作為輸入
的模組被定義於 "Include/opcode.h" 並且被編譯器和直譯器所使用。

**CPython implementation detail:** 字节码是 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" 是行号)。


32.12.1. 字节码分析
===================

3.4 版新加入.

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

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

   Analyse the bytecode corresponding to a function, generator,
   method, string of source code, or a code object (as returned by
   "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()" 。

示例:

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


32.12.2. 分析函数
=================

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

dis.code_info(x)

   Return a formatted multi-line string with detailed code object
   information for the supplied function, generator, method, source
   code string or code object.

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

   3.2 版新加入.

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)

   Disassemble the *x* object.  *x* can denote either a module, a
   class, a method, a function, a generator, a code object, a string
   of source code or a byte sequence of raw bytecode.  For a module,
   it disassembles all functions. For a class, it disassembles all
   methods (including class and static methods). For a code object or
   sequence of raw bytecode, it prints one line per bytecode
   instruction.  Strings are first compiled to code objects with the
   "compile()" built-in function before being disassembled.  If no
   object is provided, this function disassembles the last traceback.

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

   3.4 版更變: 添加 *file* 参数。

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_firstlineno" 和 "co_lnotab"
   属性来查找源代码中行开头的偏移量。它们生成为 "(offset, lineno)` `对
   。请参阅 :source:`objects/lnotab_notes.txt` ，了解 ``co_lnotab" 格
   式以及如何解码它。

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

dis.findlabels(code)

   Detect all offsets in the code object *code* which are jump
   targets, and return a list of these offsets.

dis.stack_effect(opcode[, oparg])

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

   3.4 版新加入.


32.12.3. 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

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

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

   Implements "TOS = get_awaitable(TOS.__aiter__())".  See
   "GET_AWAITABLE" for details about "get_awaitable"

   3.5 版新加入.

GET_ANEXT

   实现 "PUSH(get_awaitable(TOS.__anext__()))" 。参见 "GET_AWAITABLE"
   获取更多 "get_awaitable" 的细节

   3.5 版新加入.

BEFORE_ASYNC_WITH

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

   3.5 版新加入.

SETUP_ASYNC_WITH

   创建一个新的帧对象。

   3.5 版新加入.

**其他操作码**

PRINT_EXPR

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

BREAK_LOOP

   Terminates a loop due to a "break" statement.

CONTINUE_LOOP(target)

   Continues a loop due to a "continue" statement.  *target* is the
   address to jump to (which should be a "FOR_ITER" instruction).

SET_ADD(i)

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

LIST_APPEND(i)

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

MAP_ADD(i)

   Calls "dict.setitem(TOS1[-i], TOS, TOS1)".  Used to implement dict
   comprehensions.

   3.1 版新加入.

对于所有 "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

   Removes one block from the block stack.  Per frame, there is a
   stack of blocks, denoting nested loops, try statements, and such.

POP_EXCEPT

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

END_FINALLY

   Terminates a "finally" clause.  The interpreter recalls whether the
   exception has to be re-raised, or whether the function returns, and
   continues with the outer-next block.

LOAD_BUILD_CLASS

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

SETUP_WITH(delta)

   This opcode performs several operations before a with block starts.
   First, it loads "__exit__()" from the context manager and pushes it
   onto the stack for later use by "WITH_CLEANUP".  Then,
   "__enter__()" is called, and a finally block pointing to *delta* is
   pushed.  Finally, the result of calling the enter method is pushed
   onto the stack.  The next opcode will either ignore it ("POP_TOP"),
   or store it in (a) variable(s) ("STORE_FAST", "STORE_NAME", or
   "UNPACK_SEQUENCE").

   3.2 版新加入.

WITH_CLEANUP_START

   Cleans up the stack when a "with" statement block exits.  TOS is
   the context manager's "__exit__()" bound method. Below TOS are 1--3
   values indicating how/why the finally clause was entered:

   * SECOND = "None"

   * (SECOND, THIRD) = ("WHY_{RETURN,CONTINUE}"), retval

   * SECOND = "WHY_*"; no retval below it

   * (SECOND, THIRD, FOURTH) = exc_info()

   In the last case, "TOS(SECOND, THIRD, FOURTH)" is called, otherwise
   "TOS(None, None, None)".  Pushes SECOND and result of the call to
   the stack.

WITH_CLEANUP_FINISH

   Pops exception type and result of 'exit' function call from the
   stack.

   If the stack represents an exception, *and* the function call
   returns a 'true' value, this information is "zapped" and replaced
   with a single "WHY_SILENCED" to prevent "END_FINALLY" from re-
   raising the exception.  (But non-local gotos will still be
   resumed.)

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

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)

   The version of "BUILD_MAP" specialized for constant keys.  *count*
   values are consumed from the stack.  The top element on the stack
   contains a tuple of keys.

   3.6 版新加入.

BUILD_STRING(count)

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

   3.6 版新加入.

BUILD_TUPLE_UNPACK(count)

   从栈中弹出 *count* 个可迭代对象，将它们合并为单个元组，并将结果推入
   栈顶。 实现可迭代对象解包为元组形式 "(*x, *y, *z)"。

   3.5 版新加入.

BUILD_TUPLE_UNPACK_WITH_CALL(count)

   这类似于 "BUILD_TUPLE_UNPACK" 但专用于 "f(*x, *y, *z)" 调用语法。
   栈中 "count + 1" 位置上的项应当是相应的可调用对象 "f"。

   3.6 版新加入.

BUILD_LIST_UNPACK(count)

   这类似于 "BUILD_TUPLE_UNPACK" 但会将一个列表而非元组推入栈顶。 实现
   可迭代对象解包为列表形式 "[*x, *y, *z]"。

   3.5 版新加入.

BUILD_SET_UNPACK(count)

   这类似于 "BUILD_TUPLE_UNPACK" 但会将一个集合而非元组推入栈顶。 实现
   可迭代对象解包为集合形式 "{*x, *y, *z}"。

   3.5 版新加入.

BUILD_MAP_UNPACK(count)

   从栈中弹出 *count* 个映射对象，将它们合并为单个字典，并将结果推入栈
   顶。 实现字典解包为字典形式 "{**x, **y, **z}"。

   3.5 版新加入.

BUILD_MAP_UNPACK_WITH_CALL(count)

   这类似于 "BUILD_MAP_UNPACK" 但专用于 "f(**x, **y, **z)" 调用语法。
   栈中 "count + 2" 位置上的项应当是相应的可调用对象 "f"。

   3.5 版新加入.

   3.6 版更變: 可迭代对象的位置的确定方式是将操作码参数加 2 而不是将其
   编码到参数的第二个字节。

LOAD_ATTR(namei)

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

COMPARE_OP(opname)

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

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_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_LOOP(delta)

   Pushes a block for a loop onto the block stack.  The block spans
   from the current instruction with a size of *delta* bytes.

SETUP_EXCEPT(delta)

   Pushes a try block from a try-except clause onto the block stack.
   *delta* points to the first except block.

SETUP_FINALLY(delta)

   Pushes a try block from a try-except clause onto the block stack.
   *delta* points to the finally block.

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

STORE_ANNOTATION(namei)

   Stores TOS as "locals()['__annotations__'][co_names[namei]] = TOS".

   3.6 版新加入.

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)

   Raises an exception. *argc* indicates the number of arguments to
   the raise statement, ranging from 0 to 3.  The handler will find
   the traceback as TOS2, the parameter as TOS1, and the exception as
   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* 的最低位，则栈顶包含一个由额外关键字参数组成的映射对象。 在
   该对象之下是一个包含位置参数的可迭代对象和一个待调用的可调用对象。
   "BUILD_MAP_UNPACK_WITH_CALL" 和 "BUILD_TUPLE_UNPACK_WITH_CALL" 可用
   于合并多个映射对象和包含参数的可迭代对象。  在该可调用对象被调用之
   前，映射对象和可迭代对象会被分别“解包”并将它们的内容分别作为关键字
   参数和位置参数传入。 "CALL_FUNCTION_EX" 会从栈中弹出所有参数以及可
   调用对象，附带这些参数调用该可调用对象，并将可调用对象所返回的返回
   值推入栈顶。

   3.6 版新加入.

MAKE_FUNCTION(argc)

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

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

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

   * "0x04" 是一个标注字典

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

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

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

BUILD_SLICE(argc)

   将一个切片对象推入栈顶。 *argc* 必须为 2 或 3。 如果为 2，则推入
   "slice(TOS1, TOS)"；如果为 3，则推入 "slice(TOS2, TOS1, TOS)"。 请
   参阅 "slice()" 内置函数了解详细信息。

EXTENDED_ARG(ext)

   Prefixes any opcode which has an argument too big to fit into the
   default two bytes.  *ext* holds two additional bytes which, taken
   together with the subsequent opcode's argument, comprise a four-
   byte argument, *ext* being the two most-significant bytes.

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 版新加入.

HAVE_ARGUMENT

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

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


32.12.4. 操作码集合
===================

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

dis.opname

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

dis.opmap

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

dis.cmp_op

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

dis.hasconst

   访问常量的字节码序列。

dis.hasfree

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

dis.hasname

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

dis.hasjrel

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

dis.hasjabs

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

dis.haslocal

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

dis.hascompare

   布尔运算的字节码序列
