命名空間是命名到對象的映射.目前大多數命名空間是用Python的字典(dict)實現的,可是具體如何實現可有可無,除非出於性能的考慮,而且未來可能改變其實現方式.例如命名空間是:built-in(builtins模塊)的命名的集合,包括例如abs()函數或者built-in異常命名;函數調用的本地命名.在某種意義上對象的屬性集也是一個命名空間.關於命名空間須要明白一件很重要的事就是不一樣命名空間間絕對沒有任何關係;例如,兩個模塊可能都定義了一個函數maximize而不會混淆--用戶必須以模塊名爲前綴來引用它們.html
命名空間在不一樣的時間被建立,並有不一樣生命週期.包含built-in命名的命名空間會在GIL啓動的時候建立,並且永遠不會被刪除.對於模塊的全局命名空間在模塊的定義被讀入時建立;一般,模塊命名空間也生存到GIL退出前.不管從腳本文件或是交互的語句,在GIL的頂層調用執行的語句被認爲是__main__模塊的一部分,因此它們有它們本身的全局命名空間.
*某些程序中:if __name__==__main__ 用來判斷腳本文件是不是被GIL頂層調用,若是不是能夠屏蔽一些沒必要要的操做,例如沒必要要的提示輸出.*python
當函數被調用時它的本地or局部(local)命名空間被建立,當該函數返回(return)或拋出未被函數中處理的異常時命名空間被刪除.實際上用遺忘來描述發生了什麼更爲貼切.若是從新調用改函數,命名空間會從新建立.bash
做用域是python程序能夠直接訪問命名空間的文本區域.這裏直接訪問是指一個未綁定命名的引用在命名空間試圖找到這個命名.閉包
儘管做用域是靜態決定的,但都是動態使用的.在任何執行時刻,至少有三種嵌套做用域,其命名空間能夠直接訪問的:函數
def scope_test(): def do_local(): spam = "local spam" print('dict in do_local()',locals(),'and id',id(spam)) def do_nonlocal(): nonlocal spam spam = "nonlocal spam" print('dict in do_nonlocal()',locals(),'and id',id(spam)) def do_global(): global spam spam = "global spam" print('dict in do_global()',locals(),'and id',id(spam)) spam = "test spam" do_local() print("After local assignment:", spam,'and id',id(spam)) do_nonlocal() print("After nonlocal assignment:", spam,'and id',id(spam)) do_global() print("After global assignment:", spam,'and id',id(spam)) print('dict in scope_test',locals(),'and id',id(spam)) scope_test() print("In global scope:", spam,'and global dict',globals(),'and id',id(spam))
output:性能
dict in do_local() {'spam': 'local spam'} and id 140120830499184 After local assignment: test spam and id 140120830499440 dict in do_nonlocal() {'spam': 'nonlocal spam'} and id 140120830499248 After nonlocal assignment: nonlocal spam and id 140120830499248 dict in do_global() {} and id 140120830499376 After global assignment: nonlocal spam and id 140120830499248 dict in scope_test {'do_global': <function scope_test.<locals>.do_global at 0x7f706c52e1e0>, 'do_nonlocal': <function scope_test.<locals>.do_nonlocal at 0x7f706c52e158>, 'do_local': <function scope_test.<locals>.do_local at 0x7f706c52e0d0>, 'spam': 'nonlocal spam'} and id 140120830499248 In global scope: global spam and global dict {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x7f706c5e5080>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': '/home/katachi/PycharmProjects/OtherPrj/pythontest/namespace.py', '__cached__': None, 'scope_test': <function scope_test at 0x7f706c60be18>, 'spam': 'global spam'} and id 140120830499376
根據id和locals()的結果,do_local()中的spam屬於do_local()的本地命名空間,不能修改scope_test()中的spam.
do_nonlocal()中用關鍵字nonlocal聲明spam,該spam不是新建的,它會向外層尋找,最終綁定scope_test()中的spam.
do_global()中使用關鍵字global聲明spam,可是全局Namespace預先沒有spam,則會新建一個spam,這一點經過id()結果也看得出來.ui
簡單說,命名空間就是肯定某個命名對應的對象,而做用域則是肯定改命名究竟是哪一個命名空間的.
python肯定某個命名時,有從"內"往"外"的特色,global使得命名能夠綁定全局命名空間的對象,而nonlocal則從上一層往外尋找,直到找到或者拋出異常.spa
REF:
https://docs.python.org/3/tutorial/classes.html#python-scopes-and-namespaces
https://docs.python.org/3/reference/simple_stmts.html#nonlocal
http://www.cnblogs.com/livingintruth/p/3296010.htmlrest