變數的作用域 (scope)
在查找一個變數時,首先會去找 local namespace (function),再找 global namespace (module),再找 built-in namespace。以下為一個例子:
num = 2
def set_num_1(val):
num = val
def set_num_2(val):
global num
num = val
set_num_1(5) # num = 2
set_num_2(5) # num = 5可以看出在第一個函數中只改到了 local namespace,而第二個函數加入了 global 才讓 num 變成在 global namespace 之中。
Anonymous Function
一般的 python function 由 def 來定義,而一個被定義的函數若沒有名字則為 anonymous function。
Closure
Closure 也是個函數,但其綁定了一個環境,包含了一些 free variables 在之中。而這些 free variable 即使在定義的作用域已經無效了的時候仍然能夠被使用。以下為一個例子:
def make_averager():
series = []
def averager(val):
series.append(val)
return sum(series) / len(series)
return averager
avg = make_averager()
print(avg(1)) # 1.0
print(avg(2)) # 1.5
print(avg(3)) # 2.0
print(avg.__code__.co_varnames) # ('val',)
print(avg.__code__.co_freevars) # ('series',)
print(avg.__closure__) # (list object at 0x7f898c80ee80,)
print(avg.__closure__[0].cell_contents) # [1, 2, 3]- make_averager 為 enclosing function,而 averager 為 nested function。Nested function 用到了定義在 enclosing function 中的變數 series。
- Enclosing function 回傳 nested function。
- 綁定的 free variable 即為 series。
- 可以用 __code__ 以及 __closure__ 來了解 closure 中的細節。
關鍵字 nonlocal
以下為簡化後的 averager 的例子:
def make_averager():
count = 0
total = 0
def averager(val):
nonlocal count, total
count += 1
total += val
return total / count
return averager如果少了第六行中的 nonlocal 會發生此錯誤:local variable 'count' referenced before assignment。因此 nonlocal 的目的即為讓這兩個變數能為 free variables 而不只是 local variables。
什麼時候會用到 closure?
這篇文章有稍微介紹一個例子。
沒有留言:
張貼留言