作用域規則
命名空間是從名稱到對象的映射,Python中主要是通過字典實現的,主要有以下幾個命名空間:
內置命名空間,包含一些內置函數和內置異常的名稱,在Python解釋器啟動時創建,一直保存到解釋器退出。內置命名實際上存在于一個叫__builtins__的模塊中,可以通過globals()['__builtins__'].__dict__查看其中的內置函數和內置異常。
全局命名空間,在讀入函數所在的模塊時創建,通常情況下,模塊命名空間也會一直保存到解釋器退出。可以通過內置函數globals()查看。
局部命名空間,在函數調用時創建,其中包含函數參數的名稱和函數體內賦值的變量名稱。在函數返回或者引發了一個函數內部沒有處理的異常時刪除,每個遞歸調用有它們自己的局部命名空間。可以通過內置函數locals()查看。
python解析變量名的時候,首先搜索局部命名空間。如果沒有找到匹配的名稱,它就會搜索全局命名空間。如果解釋器在全局命名空間中也找不到匹配值,最終會檢查內置命名空間。如果仍然找不到,就會引發NameError異常。
不同命名空間內的名稱絕對沒有任何關系,比如:
a = 42def foo(): a = 13 print "globals: %s" % globals() print "locals: %s" % locals() return afoo()print "a: %d" % a
結果:
globals: {'a': 42, '__builtins__': <module '__builtin__' (built-in)>, '__file__': 'C://Users//h//Desktop//test4.py', '__package__': None, '__name__': '__main__', 'foo': <function foo at 0x0000000002C17AC8>, '__doc__': None}locals: {'a': 13}a: 42可見在函數中對變量a賦值會在局部作用域中創建一個新的局部變量a,外部具有相同命名的那個全局變量a不會改變。
在Python中賦值操作總是在最里層的作用域,賦值不會復制數據,只是將命名綁定到對象。刪除也是如此,比如在函數中運行del a,也只是從局部命名空間中刪除局部變量a,全局變量a不會發生任何改變。
如果使用局部變量時還沒有給它賦值,就會引發UnboundLocalError異常:
a = 42def foo(): a += 1 return afoo()
上述函數中定義了一個局部變量a,賦值語句a += 1會嘗試在a賦值之前讀取它的值,但全局變量a是不會給局部變量a賦值的。
要想在局部命名空間中對全局變量進行操作,可以使用global語句,global語句明確地將變量聲明為屬于全局命名空間:
a = 42def foo(): global a a = 13 print "globals: %s" % globals() print "locals: %s" % locals() return afoo()print "a: %d" % a
輸出:
globals: {'a': 13, '__builtins__': <module '__builtin__' (built-in)>, '__file__': 'C://Users//h//Desktop//test4.py', '__package__': None, '__name__': '__main__', 'foo': <function foo at 0x0000000002B87AC8>, '__doc__': None}locals: {}a: 13
新聞熱點
疑難解答