2013-10-24 6 views
15

私はPythonのバイトコードとそのdisモジュールを理解するのが大変です。pythonバイトコードを読むには?

import dis 
def func(): 
    x = 1 
dis.dis(func) 

上記のコードインタプリタで入力したときに次の出力を生成します。

0 LOAD_CONST     1(1) 
    3 STORE_FAST     0(x) 
    6 LOAD_CONST     0(NONE) 
    9 RETURN_VALUE 

例:

LOAD_CONSTSTORE_FASTの意味と0のような数字は何ですか、36および9

私はこの情報を見つけることができる特定のリソースは、非常に感謝します。バイトコードの前に

+0

この回答を読んでもわかりませんhttp://stackoverflow.com/a/12673195/973699 – DevC

+0

@DevCこの質問は読んでいますが、問題は非常に単純な機能私の質問で言及したのとまったく同じように、バイトコードで何が起こっているのかを少しはっきりと知ることができました。 –

答えて

29

番号は元のバイナリバイトコードへのオフセットです:どのように各バイトコードの動作に影響を与えるいくつかのバイトコードには、追加情報(引数)が付属して

>>> func.__code__.co_code 
'd\x01\x00}\x00\x00d\x00\x00S' 

、オフセットバイトストリームのどの位置でわかりますバイトコードが見つかりました。バイトコード(ASCII d、16進64)の後には、バイトコードに関連する定数への参照を符号化する2つの追加バイトが続きます。その結果、STORE_FASTオペコード(ASCII }、16進7D)がインデックス3に見つかります。

dis module documentationには、各命令の意味が列挙されています。 LOAD_CONSTについては、

プッシュco_consts[consti]をスタックにプッシュします。

これは、コードオブジェクトで常に存在するco_consts構造を指します。コンパイラが構築する:

>>> func.__code__.co_consts 
(None, 1) 

その構造(バイトコード符号化1 01 00バイト)、及びdisからオペコード負荷指標1はあなたのためにそれを見上げました。値は1です。

次の命令、STORE_FASTは以下のように記載されている:ローカルco_varnames[var_num]

格納TOS。

ここでTOSはTop Of Stackを指します。 LOAD_CONSTちょうど何かをスタックにプッシュしたことに注意してください。1の値です。 co_varnamesは別の構造です。

>>> func.__code__.co_varnames 
('x',) 

disあまりにもそれを見て、あなたのコードで使用される名前がxです:それはオペコード参照インデックス0は、ローカル変数名を参照します。したがって、このオペコードはをxに格納します。

RETURN_VALUE続くインデックス0からスタックへの別LOAD_CONST負荷None:関数の呼び出し元へTOSと

返し。

ので、この命令は(None定数)スタックの先頭を取得し、このコードブロックから返します。 Noneは、明示的なreturnステートメントのない関数のデフォルトの戻り値です。

あなたはdis出力、ライン番号から何かを省略:

>>> dis.dis(func) 
    2   0 LOAD_CONST    1 (1) 
       3 STORE_FAST    0 (x) 
       6 LOAD_CONST    0 (None) 
       9 RETURN_VALUE   

注最初の行に2。これは、元のソースの行番号で、これらの命令に使用されたPythonコードを含んでいます。 Pythonコードオブジェクトには、バイトコードを元のソースの行番号にマップすることを可能にするco_lnotabおよびco_firstlinenoの属性があります。 disは逆アセンブリを表示するときにこれを行います。

+0

広範な回答とドキュメントへのご意見ありがとうございます –