32.12. dis — Python バイトコードの逆アセンブラ¶
ソースコード: Lib/dis.py
dis モジュールは CPython バイトコード (bytecode) を逆アセンブルすることでバイトコードの解析をサポートします。 このモジュールが入力として受け取る CPython バイトコードはファイル Include/opcode.h に定義されており、 コンパイラとインタプリタが使用しています。
CPython 実装の詳細: バイトコードは CPython インタプリタの実装詳細です。Python のバージョン間でバイトコードの追加や、削除、変更がないという保証はありません。このモジュールを使用することによって Python の異なる VM または異なるリリースの間で動作すると考えるべきではありません。
例: 以下の関数 myfunc() を考えると
def myfunc(alist):
return len(alist)
myfunc() の逆アセンブル結果を表示するために次のコマンドを使うことができます:
>>> dis.dis(myfunc)
2 0 LOAD_GLOBAL 0 (len)
3 LOAD_FAST 0 (alist)
6 CALL_FUNCTION 1
9 RETURN_VALUE
(“2” は行番号です)。
32.12.1. バイトコード解析¶
バージョン 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()の出力において、指定された命令コード (opcode) に “現在の命令 (instruction)” を表す印が表示されます。-
classmethod
from_traceback(tb)¶ 与えられたトレースバックから
Bytecodeインスタンスを構築し、 current_offset がその例外の原因となった命令となるよう設定します。
-
codeobj¶ コンパイルされたコードオブジェクト。
-
first_line¶ コードオブジェクトのソースの最初の行 (利用可能であれば)
-
info()¶ code_info()のようなコードオブジェクトの詳細を含んだ整形された複数行文字列を返します。
-
classmethod
例
>>> bytecode = dis.Bytecode(myfunc)
>>> for instr in bytecode:
... print(instr.opname)
...
LOAD_GLOBAL
LOAD_FAST
CALL_FUNCTION
RETURN_VALUE
32.12.2. 解析関数¶
dis モジュールには、以下に挙げる入力を直接欲しい出力に変換する解析関数も定義してあります。
1つの命令だけが実行されている場合は、解析オブジェクトをいったん作るよりはこちらの方が便利です:
-
dis.code_info(x)¶ 渡された関数、ジェネレータ、メソッド、ソースコード文字列、コードオブジェクトに対する、詳細なコードオブジェクトの情報を、整形された複数行の文字列として返します。
この結果は実装に強く依存しており、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)¶ x オブジェクトを逆アセンブルします。 x はモジュール、クラス、メソッド、関数、ジェネレータ、 code オブジェクト、ソースコード文字列、バイトコードを格納したバイト列のどれかです。 モジュールに対しては、すべての関数を逆アセンブルします。 クラスに対しては、 (クラスや静的メソッドも含め) すべてのメソッドを逆アセンブルします。 code オブジェクトやバイトコード列に対しては、バイトコード1命令ごとに1行を表示します。 文字列は一旦
compile()ビルトイン関数で code オブジェクトにコンパイルしてから逆アセンブルします。 何も指定されなかった場合、この関数は最後のトレースバックを逆アセンブルします。file 引数が渡された場合は、アセンブリをそこに書き込みます。 そうでない場合は
sys.stdoutに出力します。バージョン 3.4 で変更: file 引数が追加されました。
-
dis.distb(tb=None, *, file=None)¶ トレースバックのスタックの先頭の関数を逆アセンブルします。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)の対として生成されます。
-
dis.findlabels(code)¶ ジャンプ先であるコードオブジェクト code のすべてのオフセットを 求め、これらのオフセットのリストを返します。
-
dis.stack_effect(opcode[, oparg])¶ opcode と引数 oparg がスタックに与える影響を計算します。
バージョン 3.4 で追加.
32.12.3. Python バイトコード命令¶
get_instructions() 関数と Bytecode クラスはバイトコード命令の詳細を Instruction インスタンスの形で提供します:
-
class
dis.Instruction¶ バイトコード命令の詳細
-
opcode¶ 以下の命令コードの値と 命令コードコレクション のバイトコードの値に対応する、命令の数値コードです。
-
opname¶ 人間が読むための命令名
-
arg¶ (ある場合は) 命令の数値引数、無ければ
None
-
argval¶ (もし分かっていれば) 解決された引数の値、そうでない場合は arg と同じもの
-
argrepr¶ 人間が読むための命令引数の説明
-
offset¶ バイトコード列の中での命令の開始位置
-
starts_line¶ (ある場合は) この命令コードが始まる行、無ければ
None
-
is_jump_target¶ 他のコードからここへジャンプする場合は
True、そうでない場合はFalse
バージョン 3.4 で追加.
-
現在 Python コンパイラは次のバイトコード命令を生成します。
一般的な命令
-
NOP¶ なにもしないコード。バイトコードオプティマイザでプレースホルダとして使われます。
-
POP_TOP¶ スタックの先頭 (TOS) の要素を取り除きます。
-
ROT_TWO¶ スタックの先頭の 2 つの要素を入れ替えます。
-
ROT_THREE¶ スタックの二番目と三番目の要素の位置を 1 つ上げ、先頭を三番目へ下げます。
-
DUP_TOP¶ スタックの先頭にある参照の複製を作ります。
-
DUP_TOP_TWO¶ スタックの先頭の2つの参照を、そのままの順番で複製します。
1オペランド命令
1オペランド命令はスタックの先頭を取り出して操作を適用し、結果をスタックへプッシュし戻します。
-
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 で追加.
2オペランド命令
二項命令はスタックの先頭 (TOS) と先頭から二番目の要素をスタックから取り除きます。 命令を実行し、スタックへ結果をプッシュし戻します。
-
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を実行します。
インプレース (in-place) 命令
インプレース命令は TOS と TOS1 を取り除いて結果をスタックへプッシュするという点で二項命令と似ています。 しかし、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がコルーチンオブジェクトもしくは CO_ITERABLE_COROUTINE フラグの付いたジェネレータオブジェクトの場合にoを返し、そうでない場合はo.__await__を解決します。
-
GET_AITER¶ TOS = get_awaitable(TOS.__aiter__())を実行します。get_awaitableの詳細についてはGET_AWAITABLEを参照してください。
-
GET_ANEXT¶ PUSH(get_awaitable(TOS.__anext__()))を実行します。get_awaitableの詳細についてはGET_AWAITABLEを参照してください。
-
BEFORE_ASYNC_WITH¶ スタックの先頭にあるオブジェクトの
__aenter__と__aexit__を解決します。__aexit__と__aenter__()の結果をスタックに積みます。
-
SETUP_ASYNC_WITH¶ 新たなフレームオブジェクトを作成します。
その他の命令コード
-
SET_ADD(i)¶ set.add(TOS1[-i], TOS)を呼び出します。集合内包表記の実装に使われます。
-
LIST_APPEND(i)¶ list.append(TOS1[-i], TOS)を呼び出します。リスト内包表記の実装に使われます。
-
MAP_ADD(i)¶ dict.setitem(TOS1[-i], TOS, TOS1)を呼び出します。辞書内包表記の実装に使われます。
SET_ADD, LIST_APPEND, MAP_ADD は、追加した値または key/value ペアをスタックから取り除きますが、コンテナオブジェクトはループの次のイテレーションで利用できるようにスタックに残しておきます。
-
RETURN_VALUE¶ 関数の呼び出し元へ TOS を返します。
-
IMPORT_STAR¶ '_'で始まっていないすべてのシンボルをモジュール TOS から直接ローカル名前空間へロードします。 モジュールはすべての名前をロードした後にポップされます。 この命令コードはfrom module import *を実行します。
-
POP_BLOCK¶ ブロックスタックからブロックを一つ取り除きます。 フレームごとにブロックのスタックがあり、ネストしたループや try 文などを表しています。
-
POP_EXCEPT¶ ブロックスタックからブロックを1つ取り除きます。 ポップされたブロックは、例外ハンドラに入ったときに暗黙的に生成された例外ハンドラのブロックでなければなりません。 フレームスタックから本質的でない値をポップするのに加えて、直前にポップした3つの値が例外状態を回復するのに使われます。
-
END_FINALLY¶ finally節を終了します。 インタプリタは例外を再送出しなければならないかどうか、あるいは、 関数から return して外側の次のブロックに続くかどうかを再度判断します。
-
LOAD_BUILD_CLASS¶ builtins.__build_class__()をスタックにプッシュします。 これはクラスを構築するために、後でCALL_FUNCTIONに呼ばれます。
-
SETUP_WITH(delta)¶ この命令コードは、with ブロックが開始する前にいくつかの命令を行います。 まず、コンテキストマネージャから
__exit__()をロードし、 後からWITH_CLEANUPで使うためにスタックにプッシュします。 そして、__enter__()が呼び出され、 delta を指す finally ブロックがプッシュされます。最後に、enter メソッドを呼び出した 結果がスタックにプッシュされます。次の命令コードはこれを無視 (POP_TOP) するか、変数に保存 (STORE_FAST,STORE_NAME, またはUNPACK_SEQUENCE) します。
-
WITH_CLEANUP_START¶ with式ブロックを抜けるときに、スタックをクリーンアップします。 TOS はコンテキストマネージャの__exit__()メソッドです。 TOS の下は 1–3 個の値で、それらはなぜ/どのように finally 節に 到達したかを表しています:- SECOND =
None - (SECOND, THIRD) = (
WHY_{RETURN,CONTINUE}), retval - SECOND =
WHY_*; no retval below it - (SECOND, THIRD, FOURTH) = exc_info()
最後のケースでは
TOS(SECOND, THIRD, FOURTH)が呼び出され、それ以外ではTOS(None, None, None)が呼び出されます。 SECOND と先程の呼び出し結果がスタックにプッシュされます。- SECOND =
-
WITH_CLEANUP_FINISH¶ 例外の型と ‘exit’ 関数を呼び出した結果をスタックからポップします。
スタックが例外処理中の状態を示し、 かつ 関数呼び出しが ‘true’ 値を返した場合、
END_FINALLYが例外を再送出するのを防ぐため、この情報を無かったことにして単一のWHY_SILENCEDで置き換えます。 (ただし、 non-local goto は再開されます。)
以下の命令コードはすべて引数を必要とします。引数は 2 バイトで、最上位バイトが後になります。
-
STORE_NAME(namei)¶ name = TOSを実行します。 namei はコードオブジェクトの属性co_namesにおける name のインデックスです。 コンパイラは可能ならばSTORE_FASTまたはSTORE_GLOBALを使おうとします。
-
DELETE_NAME(namei)¶ del nameを実行します。 namei はコードオブジェクトのco_names属性へのインデックスです。
-
UNPACK_SEQUENCE(count)¶ TOS を count 個の個別の値にアンパックして、右から左の順にスタックに積みます。
-
UNPACK_EX(counts)¶ 星付きの対象ありの代入を実行します: TOS にあるイテラブルを個別の値にばらしますが、ばらした値の総数はイテラブルの要素数より小さくなることがあります: そのときは、値の1つはばらされずに残った要素からなるリストです。
counts の下位バイトはそのリスト値より前にある値の個数で、 counts の上位バイトはそれより後ろにある値の個数です。 そうしてできた値は右から左の順でスタックに積まれます。
-
STORE_ATTR(namei)¶ TOS.name = TOS1を実行します。 namei はco_namesにおける名前のインデックスです。
-
DELETE_ATTR(namei)¶ del TOS.nameを実行します。co_namesへのインデックスとして namei を使います。
-
STORE_GLOBAL(namei)¶ STORE_NAMEと同じように動作しますが、 name をグローバルとして保存します。
-
DELETE_GLOBAL(namei)¶ DELETE_NAMEと同じように動作しますが、グローバルの 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と同じように動作しますが、この命令は set を作り出します。
-
BUILD_MAP(count)¶ Pushes a new dictionary object onto the stack. Pops
2 * countitems so that the dictionary holds count entries:{..., TOS3: TOS2, TOS1: TOS}.バージョン 3.5 で変更: The dictionary is created from stack items instead of creating an empty dictionary pre-sized to hold count items.
-
BUILD_TUPLE_UNPACK(count)¶ Pops count iterables from the stack, joins them in a single tuple, and pushes the result. Implements iterable unpacking in tuple displays
(*x, *y, *z).バージョン 3.5 で追加.
-
BUILD_LIST_UNPACK(count)¶ This is similar to
BUILD_TUPLE_UNPACK, but pushes a list instead of tuple. Implements iterable unpacking in list displays[*x, *y, *z].バージョン 3.5 で追加.
-
BUILD_SET_UNPACK(count)¶ This is similar to
BUILD_TUPLE_UNPACK, but pushes a set instead of tuple. Implements iterable unpacking in set displays{*x, *y, *z}.バージョン 3.5 で追加.
-
BUILD_MAP_UNPACK(count)¶ Pops count mappings from the stack, merges them into a single dictionary, and pushes the result. Implements dictionary unpacking in dictionary displays
{**x, **y, **z}.バージョン 3.5 で追加.
-
BUILD_MAP_UNPACK_WITH_CALL(oparg)¶ This is similar to
BUILD_MAP_UNPACK, but is used forf(**x, **y, **z)call syntax. The lowest byte of oparg is the count of mappings, the relative position of the corresponding callablefis encoded in the second byte of oparg.バージョン 3.5 で追加.
-
LOAD_ATTR(namei)¶ TOS を
getattr(TOS, co_names[namei])と入れ替えます。
-
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 が真ならば、バイトコードカウンタを target に設定します。 TOS はポップされます。
-
POP_JUMP_IF_FALSE(target)¶ TOS が偽ならば、バイトコードカウンタを target に設定します。 TOS はポップされます。
-
JUMP_IF_TRUE_OR_POP(target)¶ TOS が真ならば、バイトコードカウンタを target に設定し、TOS は スタックに残されます。そうでない (TOS が偽) なら、TOS はポップされます。
-
JUMP_IF_FALSE_OR_POP(target)¶ TOS が偽ならば、バイトコードカウンタを target に設定し、TOS は スタックに残されます。そうでない (TOS が真) なら、TOS はポップされます。
-
JUMP_ABSOLUTE(target)¶ バイトコードカウンタを target に設定します。
-
FOR_ITER(delta)¶ TOS はイテレータです。 その
__next__()メソッドを呼び出します。 新しい値が yield された場合は、それをスタックにプッシュします (イテレータはその下に残されます)。 イテレータの呼び出しで要素が尽きたことが示された場合は、 TOS がポップされ、バイトコードカウンタが delta だけ増やされます。
-
LOAD_GLOBAL(namei)¶ co_names[namei]という名前のグローバルをスタック上にロードします。
-
SETUP_LOOP(delta)¶ ループのためのブロックをブロックスタックにプッシュします。 ブロックは現在の命令から delta バイトの大きさを占めます。
-
SETUP_EXCEPT(delta)¶ try-except 節から try ブロックをブロックスタックにプッシュします。 delta は最初の except ブロックを指します。
-
SETUP_FINALLY(delta)¶ try-except 節から try ブロックをブロックスタックにプッシュします。 delta は finally ブロックを指します。
-
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とほぼ同じですが、セルを調べる前にまずローカルの辞書を確認します。 これはクラス本体に自由変数を読み込むために使います。
-
STORE_DEREF(i)¶ セルと自由変数の記憶領域のスロット i に含まれるセルへTOSを保存します。
-
RAISE_VARARGS(argc)¶ 例外を発生させます。 argc は raise 文へ与えるパラメタの数を 0 から 3 の 範囲で示します。 ハンドラは TOS2 をトレースバック、TOS1 をパラメタ、TOS を例外として探します。
-
CALL_FUNCTION(argc)¶ 関数を呼び出します。 argc の下位バイトは位置パラメタの数を、上位バイトはキーワードパラメタの数を示します。 スタック上では、最初にキーワードパラメタが見つかります。 それぞれのキーワード引数に対しては、値がキーより上に来ます。 スタック上のキーワードパラメタの下に位置パラメタがあり、最も右のパラメタが先頭になります。 スタック上のパラメタの下には、呼び出される関数オブジェクトが置かれます。 すべての関数引数をポップし、関数自体もスタックから取り除き、戻り値をプッシュします。
-
MAKE_FUNCTION(argc)¶ 新しい関数オブジェクトをスタックにプッシュします。 スタックの下から上の順に、以下の構成でなければなりません。
argc & 0xFF位置の順序で並べたデフォルト引数オブジェクト(argc >> 8) & 0xFF名前付き引数のみについて、名前とデフォルト引数のペアをスタック上で名前がオブジェクトのすぐ下にくるように並べたもの(argc >> 16) & 0x7FFF仮引数のアノテーションオブジェクトアノテーションに対応する仮引数名を並べたタプル (アノテーションがある場合のみ)
関数に関連付けられたコード (TOS1の位置)
関数の qualified name (TOSの位置)
-
MAKE_CLOSURE(argc)¶ 新しい関数オブジェクトを生成し、その __closure__ スロットを設定し、スタックにプッシュします。 TOS は関数の qualified name であり、 TOS1 は関数に関連付けられたコードであり、 TOS2 はクロージャの自由変数のセルからなるタプルです。 argc は
MAKE_FUNCTIONによって解釈されます; アノテーションとデフォルト引数は、スタックの下にある TOS2 と同じ順序です。
-
BUILD_SLICE(argc)¶ スライスオブジェクトをスタックにプッシュします。 argc は2あるいは3でなければなりません。 2 ならば
slice(TOS1, TOS)がプッシュされます。 3 ならばslice(TOS2, TOS1, TOS)がプッシュされます。 これ以上の情報については、slice()組み込み関数を参照してください。
-
EXTENDED_ARG(ext)¶ デフォルトの 2 バイトに収まりきらない大きな引数を持つあらゆる命令コードの前に置かれます。 ext は追加の 2 バイトを保持し、後続の命令コードの引数と組み合わされます。 それらは 4 バイト引数を構成し、 ext はその最上位バイトです。
-
CALL_FUNCTION_VAR(argc)¶ 関数を呼び出します。 argc は
CALL_FUNCTIONと同じように解釈されます。 スタックの先頭の要素は可変引数リストを含んでおり、その後にキーワード引数と位置引数が続きます。
-
CALL_FUNCTION_KW(argc)¶ 関数を呼び出します。 argc は
CALL_FUNCTIONと同じように解釈されます。 スタックの先頭の要素はキーワード引数辞書を含んでおり、その後に明示的なキーワード引数と位置引数が続きます。
-
CALL_FUNCTION_VAR_KW(argc)¶ 関数を呼び出します。 argc は
CALL_FUNCTIONと同じように解釈されます。 スタックの先頭の要素はキーワード引数辞書を含んでおり、その後に変数引数のタプルが続き、 さらに明示的なキーワード引数と位置引数が続きます。
-
HAVE_ARGUMENT¶ これは実際の命令コードではありません。引数を取らない命令コード
< 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¶ ブール命令のバイトコードのリスト。
