變數的作用域 (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?
這篇文章有稍微介紹一個例子。
沒有留言:
張貼留言