Python が dis モジュールを使用して Python をバイトコードに逆コンパイルする方法の詳細な説明

WBOY
リリース: 2016-06-16 08:47:45
オリジナル
1526 人が閲覧しました

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 ファイルはディスク上のバイトコードの表現です。
Python コードを例にとると、test.__code__.co_code はテスト関数のバイトコード命令シーケンスを表します。
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, 125, 0, 0, 124, 0, 0, 100, 2, 0, 107, 0, 0, 114, 22, 0, 100, 3, 0, 83, 100, 4、0、83、100、0、0、83]

[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) に直接接続されていることがわかります。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!