dis — Python バイトコードの逆アセンブラ。Python コードをバイトコード命令に逆アセンブルします。
とても使いやすい:
python -m dis xxx.py
Python コードはまずバイトコードにコンパイルされ、次にそのバイトコードが Python 仮想マシンによって実行されます。Python バイトコードはアセンブリ命令に似た中間言語であり、仮想マシンはバイトコード命令を実行します。 1 つずつ実行してプログラムの実行を完了します。
Python dis モジュールは、Python コードの逆アセンブリをサポートし、バイトコード命令を生成します。
while 1 のほうが while True よりも速いということをインターネットで見たとき、なぜこのような違いがあるのでしょうか?
したがって、さらに深く掘り下げるには dis を使用します。
est_while.py コードが次のとおりであると仮定します。
#coding=utf-8 while 1: pass while True: pass
以下はdisを使った分析です。
E:\>python -m dis test_while.py 2 0 SETUP_LOOP 3 (to 6) 3 >> 3 JUMP_ABSOLUTE 3 5 >> 6 SETUP_LOOP 10 (to 19) >> 9 LOAD_NAME 0 (True) 12 POP_JUMP_IF_FALSE 18
while 1 (行 3) では、直接 JUMP_ABSOLUTE 命令であることがわかります。
ここ (5 行目) は True ですが、LOAD_NAME 命令と POP_JUMP_IF_FALSE 命令で構成されています。
True は python2 のキーワードではなく、値 1 の組み込み変数 bool 型であることがわかります。つまり、True+True は 2 を出力します。
また、値を割り当てることもできます。たとえば、値 True = 2、または値 True = False などです。
したがって、True の場合、命令 LOAD_NAME に対応して、ループするたびに True の値をチェックする必要があります。
これが、while True が while 1 よりも遅い理由です。
ただし、python3 では True がキーワードになります。while 1 と while True の命令は同じです。
もう一度小さな例を見てみましょう:
In[6]: def test(): ... x = 1 ... if x < 3: ... return "yes" ... else: ... return "no"
最初の命令を例にとると、最初の列の数字 (2) は、対応するソース コードの行数を示します。 2 列目の数字はバイトコードのインデックスで、命令 LOAD_CONST は位置 0 にあります。 3 番目の列は、人間が判読できるコマンド自体の名前です。 4 番目の列は命令のパラメータを表します。列 5 は計算後の実際のパラメータです。 「>>」はジャンプ先を示し、列 4 の「22」はインデックス 22 にジャンプする命令を示します。 Python コードはコンパイル プロセス中に CodeObject を生成します。CodeObject は仮想マシン内の抽象表現であり、Python C ソース コードでは PyCodeObject として表され、生成された .pyc ファイルはディスク上のバイトコードの表現です。
In[7]: import dis In[8]: dis.dis(test) 2 0 LOAD_CONST 1 (1) 3 STORE_FAST 0 (x) 3 6 LOAD_FAST 0 (x) 9 LOAD_CONST 2 (3) 12 COMPARE_OP 0 (<) 15 POP_JUMP_IF_FALSE 22 4 18 LOAD_CONST 3 ('yes') 21 RETURN_VALUE 6 >> 22 LOAD_CONST 4 ('no') 25 RETURN_VALUE 26 LOAD_CONST 0 (None) 29 RETURN_VALUE
code = [ord(i) for i in list(test.__code__.co_code)] print code
[100, 1, 0] シーケンスを例として、dis によって出力されたバイトコード命令を比較します。 100 は、Python バイトコード定義のインデックス (Python コードでは ) を表します。 これは、dis.opname[100] (LOAD_CONST) を通じて表示できます。次の 2 バイトは命令のパラメータを表します。 dis によって出力されるバイトコード命令では、
2 番目の列のバイトコード インデックスは、co_code シーケンス内の現在の命令の位置を参照します。
dis によって出力されるバイトコード命令の中には、パラメーターを持たない命令もあります。これは、co_code 83 (RETURN_VALUE) が次の命令 100 (LOAD_CONST) に直接接続されていることがわかります。