2014-10-03 74 views
13

說我這樣做:爲什麼類定義總是產生相同的字節碼?

#!/usr/bin/env python 
# encoding: utf-8 

class A(object): 
    pass 

現在我拆開它:

python -m dis test0.py 
    4   0 LOAD_CONST    0 ('A') 
       3 LOAD_NAME    0 (object) 
       6 BUILD_TUPLE    1 
       9 LOAD_CONST    1 (<code object A at 0x1004ebb30, file "test0.py", line 4>) 
      12 MAKE_FUNCTION   0 
      15 CALL_FUNCTION   0 
      18 BUILD_CLASS   
      19 STORE_NAME    1 (A) 
      22 LOAD_CONST    2 (None) 
      25 RETURN_VALUE   

現在我添加一些語句在類定義:

#!/usr/bin/env python 
# encoding: utf-8 

class A(object): 
    print 'hello' 
    1+1 
    pass 

我再次拆解:

4   0 LOAD_CONST    0 ('A') 
       3 LOAD_NAME    0 (object) 
       6 BUILD_TUPLE    1 
       9 LOAD_CONST    1 (<code object A at 0x1004ebb30, file "test0.py", line 4>) 
      12 MAKE_FUNCTION   0 
      15 CALL_FUNCTION   0 
      18 BUILD_CLASS   
      19 STORE_NAME    1 (A) 
      22 LOAD_CONST    2 (None) 
      25 RETURN_VALUE   

新的字節碼中不會出現什麼新的字符?

回答

17

新的語句存儲在嵌套的字節碼中。您可以在拆卸看到另一個代碼對象加載:

 9 LOAD_CONST    1 (<code object A at 0x1004ebb30, file "test0.py", line 4>) 

你需要檢查代碼對象,而不是。這是因爲類的主體就像一個函數對象一樣被執行,並且調用產生的本地名稱空間被用來形成類成員。

演示:

>>> import dis 
>>> def wrapper(): 
...  class A(object): 
...   pass 
... 
>>> dis.dis(wrapper) 
    2   0 LOAD_CONST    1 ('A') 
       3 LOAD_GLOBAL    0 (object) 
       6 BUILD_TUPLE    1 
       9 LOAD_CONST    2 (<code object A at 0x104b99930, file "<stdin>", line 2>) 
      12 MAKE_FUNCTION   0 
      15 CALL_FUNCTION   0 
      18 BUILD_CLASS   
      19 STORE_FAST    0 (A) 
      22 LOAD_CONST    0 (None) 
      25 RETURN_VALUE   
>>> dis.dis(wrapper.__code__.co_consts[2]) 
    2   0 LOAD_NAME    0 (__name__) 
       3 STORE_NAME    1 (__module__) 

    3   6 LOAD_LOCALS   
       7 RETURN_VALUE   

這是相同的設置你的第一個樣本;通過wrapper.__code__.co_consts元組訪問類體,這是LOAD_CONST字節代碼引用的內容;該指數給出爲2

現在,我們可以添加一個類體:

>>> def wrapper(): 
...  class A(object): 
...   print 'hello' 
...   1+1 
...   pass 
... 
>>> dis.dis(wrapper) 
    2   0 LOAD_CONST    1 ('A') 
       3 LOAD_GLOBAL    0 (object) 
       6 BUILD_TUPLE    1 
       9 LOAD_CONST    2 (<code object A at 0x104b4adb0, file "<stdin>", line 2>) 
      12 MAKE_FUNCTION   0 
      15 CALL_FUNCTION   0 
      18 BUILD_CLASS   
      19 STORE_FAST    0 (A) 
      22 LOAD_CONST    0 (None) 
      25 RETURN_VALUE   
>>> dis.dis(wrapper.__code__.co_consts[2]) 
    2   0 LOAD_NAME    0 (__name__) 
       3 STORE_NAME    1 (__module__) 

    3   6 LOAD_CONST    0 ('hello') 
       9 PRINT_ITEM   
      10 PRINT_NEWLINE  

    4   11 LOAD_CONST    2 (2) 
      14 POP_TOP    

    5   15 LOAD_LOCALS   
      16 RETURN_VALUE   

現在類主體出現;我們可以看到加載類體時會執行的字節碼。

值得注意的是爲每個班級機構執行的LOAD_NAMESTORE_NAME字節碼;那些檢索模塊名稱並將它們作爲新的本地名稱__module__存儲,以便您的課程在創建後最終會獲得__module__屬性。

LOAD_LOCALS字節碼,然後收集所有在這個「功能」產生的本地名稱,並返回給調用者,從而使BUILD_CLASS字節碼可以一起使用與'A'字符串和object基地的元組(與BUILD_TUPLE創建)產生你的新類對象。

+0

甜。不知道。有趣的問題和一個很好的答案。 (1) – NPE 2014-10-03 15:31:32

相關問題