讓我們來討論一下這個簡單的語句:
1 2 |
a = 10 |
這裡做了物件賦值(assign)這個行為,也可以說這個變數名稱(variable name)綁定(bound)到某物件上,這個物件可以透過變數(a)來訪問,但要注意…不是在程式碼任何一處都可以!
先來理解一下這些概念:
- scope(lexical): 簡單來說,就是變數宣告(綁定)的地方
-
namespace: 命名空間紀錄這些綁定行為,每個scope都會有一份命名空間的字典來提供查找
Scope的類型
- global scope
- 或稱module scope,範圍是單個檔案(*.py)
- 模組(或app)是層層堆疊起來的,並不會說哪裡才是真正的global環境,要說的話,最接近的可能就是built-in的變數如True、None所宣告的地方吧
- local scope(in compile time)
以function為範圍,scope伴隨函式被呼叫時建立,變數重新綁定
當在特定的scope下找不到特定的變數,python會往外部的命名空間查找,順序是local>global>built-in
。例如:
1 2 3 4 5 6 7 |
# module1.py a = 10 def func(): print(a) # a is global print(b) func() # raise NameError |
a
在module scope被找到,print
最後在built-in scope被找到,但找不到b
,導致NameError
對於外部的scope已經存在的變數,在當前的scope再宣告一個同樣的變數名稱,這個動作叫做mask,因為在不同的scope,這樣做並不會影響到外部的變數(某個版本以前的list comprehension會發生這種狀況),除非有意為之
透過關鍵字global
、nonlocal
來操作
1 2 3 4 5 6 7 8 9 |
a = 10 def func1(): a = 0 # a is local def func2(): global a a = 0 # a is global |
要注意nonlocal向外訪問只能訪問local scope的變數
1 2 3 4 5 6 7 |
def outer_func(): x = 10 def inner_func(): nonlocal x x = 0 # a is non-local inner_func() |
此外,可以透過函數globals
、locals
輸出該scope的所有變數: