32.12.3.Python字节码说明¶
classdis.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) 相关联的代码
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 带有参数。