2013-01-03 56 views
0

我以爲Python是一種解釋型語言,但根據下面的代碼片段,它顯然不是正在做我所期望的?我做了一些搜索,事實證明,如果在函數中有一個賦值,python會'隱式地聲明'一個名字。所以它在解釋代碼時做了一些靜態分析,但我的問題是多少?例如如下面的代碼所示,不會因爲x = 1不可達而優化?我們是否有更多關於我們如何解釋代碼的細節?感謝Python代碼是如何解釋的以及有多少靜態分析?

x = 10 
def f(): 
    if False: x = 1 
    print x 
UnboundLocalError: local variable 'x' referenced before assignment 

回答

2

在CPython的,代碼首先被編譯成字節碼,並且字節碼然後由解釋器執行。因此,在執行任何代碼之前會捕獲一些問題(語法錯誤等)。

如果你願意,你可以使用dis模塊檢查字節碼:

>>> import dis 
>>> dis.dis(f) 
    3   0 LOAD_GLOBAL    0 (False) 
       3 POP_JUMP_IF_FALSE  15 
       6 LOAD_CONST    1 (1) 
       9 STORE_FAST    0 (x) 
      12 JUMP_FORWARD    0 (to 15) 

    4  >> 15 LOAD_FAST    0 (x) 
      18 PRINT_ITEM   
      19 PRINT_NEWLINE  
      20 LOAD_CONST    0 (None) 
      23 RETURN_VALUE   

正如你所看到的,這個特殊的CPython不Python的轉換成字節碼的時候做了很多優化。

+0

啊,這是非常有用的工具:) – John

2

這裏沒有「靜態分析」,至少不像通常所解釋的那樣。只是彙編。

當你到達一個def塊結束時,編譯器被稱爲對身體把它變成一個code對象,幾乎以同樣的方式一行在REPL中輸入編譯器被調用。

它不關心分配發生在if聲明中,永遠不會發生。它仍編譯該if塊內的代碼。因此,它正在編寫一個分配到x。編譯def塊的一部分是創建locals字典,編譯該賦值時,它知道x是一個局部變量而不是全局變量,這就是它所需要的。

+1

編譯器在模塊中的任何代碼執行之前完成了所有的工作,所以當你到達def的結尾時,談論編譯器做任何事情是沒有意義的塊'。當你到達一個'def'時會發生什麼,一個函數對象是從編譯模塊時創建的代碼對象中創建的。 – Duncan