# Closure 內部函式可以扮演 closure 的角色 這是一種由「其他的函式動態」生成的函式,可以「更改或記得」函式之外的程式所建立的「變數的值」。 ### 作用域 作用域的概念就是變量可以被感知的空間範圍(scope)。 LEGB法則: Python按照優先級搜索4個作用域在第一處找到的地方停止。如果沒有找到,則會發出NameError錯誤,以確定該變量名的意義。 1. Local(局部作用域): 於function或是class內宣告的變數名 2. Enclosing: 作用於閉包函數外的函數(上一層巢狀結構中def或lambda)的作用域 3. Global(全局作用域): 最上層位於模組(module)的全域變數名稱 4. Builtin(內置作用域): 內建模組(module)的名稱,例如print, abs()這樣的函式等 ```python= age =5 # global variable def dog(): age = 10 # local variable def print_age(): print(age) # captured variable = 10 # age = age + 1 # UnboundLocalError: local variable 'age' referenced before assignment return print_age if __name__ == "__main__": dog_1 = dog() dog_1() ``` * function 中的 variable 其 life cycle(生命週期)會隨著 function 執行完而消滅。但variable age 是在 function dog() 的 scope 裡,理論上在10行 call 完 dog() 後就消失,但在11行 call dog_1() ( call print_age() ),卻能找到 variable age。 * 因為 return function print_age 時,function print_age 偷偷 capture 住 variable age,也就是把原本屬於上一層的變數偷渡到自己的 function scope ,而被捕捉的 variable 就是 captured variable!而帶有 captured variable 的 function 就稱為 **Closure** (function)! * 在6行操作 captured variable,會噴出 UnboundLocalError。因為在 function scope 裡,variable 如果要被 assign 的話,Python 會自動將 variable 定為 local variable 而不是 captured variable,所以找不到。 * 因此需定義 captured variable 不是 local variable;或是將variable 傳入function print_age。 ```python= def dog(): age = 10 def print_age(): nonlocal age print(age) # 10 age = age + 1 print(age) # 11 return print_age if __name__ == "__main__": dog_1 = dog() dog_1() ------------------------------------ def dog(): age = 10 def print_age(age): print(age) # 10 age = age + 1 print(age) # 11 return print_age(age) if __name__ == "__main__": dog_1 = dog() dog_1 ```