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" 是行号)。
字节码分析¶
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()
将针对指定的操作码显示“当前指令”标记。-
codeobj
¶ 已编译的代码对象。
-
first_line
¶ 代码对象的第一个源代码行(如果可用)
-
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 ,则指示最后一条指令。输出分为以下几列:
行号,用于每行的第一条指令
当前指令,表示为
-->
,一个标记的指令,用
>>
表示,指令的地址,
操作码名称,
操作参数,和
括号中参数的解释。
参数解释识别本地和全局变量名称、常量值、分支目标和比较运算符。
如果提供的话,反汇编将作为文本写入提供的 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)
对。请参阅 objects/lnotab_notes.txt ,了解co_lnotab
格式以及如何解码它。3.6 版更變: 行号可能会减少。 以前,他们总是在增加。
-
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
¶ 字节码操作的详细信息
-
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
¶ 实现
PUSH(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 版新加入.
其他操作码
-
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 到函数的调用者。
-
SETUP_ANNOTATIONS
¶ 检查
__annotations__
是否在locals()
中定义,如果没有,它被设置为空dict
。只有在类或模块体静态地包含 variable annotations 时才会发出此操作码。3.6 版新加入.
-
IMPORT_STAR
¶ 将所有不以
'_'
开头的符号直接从模块 TOS 加载到局部命名空间。加载所有名称后弹出该模块。这个操作码实现了from module import *
。
-
POP_EXCEPT
¶ 从块堆栈中删除一个块。 弹出的块必须是异常处理程序块,在进入 except 处理程序时隐式创建。除了从帧堆栈弹出无关值之外,最后三个弹出值还用于恢复异常状态。
-
RERAISE
¶ 重新引发当前位于栈顶的异常。
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 版新加入.
以下所有操作码均使用其参数。
-
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 个空位中的单元内并释放可用存储空间。
-
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)
-
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 版新加入.
-
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
¶ 布尔运算的字节码序列。