2010-06-28 76 views
4

這需要我深入挖掘Python源代碼,但是由於已經有很多人已經完成了這些工作,我很樂意聽到他們的指示。Python變量作用域如何工作?

>>> import os 
>>> def scope(): 
...  print os 
...  import os 
... 
>>> scope() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 2, in scope 
UnboundLocalError: local variable 'os' referenced before assignment 

在我看來,當分析器解釋文件,它會自動創建範圍功能,使OS「超脫」從全球範圍內局部範圍。

這是真的嗎?任何人都在意我可以在哪裏找到關於範圍實施的更多信息?

編輯:此外,這不是進口的特例,這也適用於通常的變量。

回答

5

當你調用scope() Python看到你有你的方法(從內scopeimport),所以這掩蓋了全球os內部使用所謂的os的局部變量。但是,如果您說print os您尚未到達線路並執行本地導入,那麼您在分配之前就會看到有關參考的錯誤。這裏有一對夫婦的其他例子,可以幫助:

>>> x = 3 
>>> def printx(): 
...  print x # will print the global x 
... 
>>> def printx2(): 
...  print x # will try to print the local x 
...  x = 4 
... 
>>> printx() 
3 
>>> printx2() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 2, in printx2 
UnboundLocalError: local variable 'x' referenced before assignment 

而且要回你的os例子。任何分配到os具有相同的效果:

>>> os 
<module 'os' from 'C:\CDL_INSTALL\install\Python26\lib\os.pyc'> 
>>> def bad_os(): 
...  print os 
...  os = "assigning a string to local os" 
... 
>>> bad_os() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 2, in bad_os 
UnboundLocalError: local variable 'os' referenced before assignment 

最後,比較這些2個例子:

>>> def example1(): 
...  print never_used # will be interpreted as a global 
... 
>>> def example2(): 
...  print used_later # will be interpreted as the local assigned later 
...  used_later = 42 
... 
>>> example1() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 2, in example1 
NameError: global name 'never_used' is not defined 
>>> example2() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 2, in example2 
UnboundLocalError: local variable 'used_later' referenced before assignment 
+0

謝謝 - 但有沒有任何有關內部實施的參考?我想看看如何解析器實際工作。它是否使Python爲每個範圍創建字典/結構,並且只在內部範圍內沒有任何東西時才查找外部範圍?只是想清除我的想法。 – Almad 2010-06-28 10:02:54

+2

這不是一個解析器問題,它是一個運行時「找到與名稱匹配x最接近的範圍」的東西。 – 2010-06-28 14:28:45

0

在函數內部的變量的任何結合使得可變局部的功能。 importdefclass都等同於這方面的分配。

所以是的,當編譯器編譯你的文件時,它會創建一個局部變量os,它的範圍與全局os分開。

有關更多信息,請參閱Python教程。特別是http://docs.python.org/tutorial/classes.html第9.2節

+0

更詳細的參考資料是http://docs.python.org/reference/executionmodel.html – Mark 2010-06-28 09:36:28

1

詞法作用域是一種常見的事情,並且大多數設計良好的語言,無論是解釋還是編譯使用它。

我已經有一段時間沒有試過,但要注意漂亮的「全球性」的關鍵字,它的下面使用:

o = 1 
def foo(): 
    global o 
    o = 2 
foo() 
print o 

,未經「環球」行,修改鄰是局部的,並且「打印o「打印1.隨着」全局o「行包括,它打印2.我們這樣稱呼我的功能(沒有全球o)上面會有它自己的變量。上述全局事件是專門請求正常詞彙範圍界定的例外的一種方式。

真正的詞法範圍是Python 1.0缺乏的東西,也是Python已經存在了很長一段時間(至少1.6,如果我沒有記錯的話)。只有兩個範圍,本地和全局範圍,並且任何中間範圍都無法訪問。