閉包
通俗地說,就是函數嵌套(後續稱之爲外層函數)另一個函數(後續稱之爲內層函數),在內層函數中,引用外層函數的變量,每次對內層函數的調用,外層函數變量的值都會進行保持。函數
用個簡單的例子來講明,使用閉包實現一個函數,求全部傳入的數字的平均值。spa
def averager(): """ 閉包實現求平均值的例子 每次傳入一個數字,返回全部傳入的數字的平均值 :return: """ count = 0 total = 0.0 def _averager(value): nonlocal total, count total += value count += 1 average = total/count return average return _averager # 調用外層函數averager,獲得內層函數_averager的對象,賦值給avg # 此時閉包造成,外層函數的變量total, count, average會被保持 avg = averager() # 每次調用內層函數avg時,外層函數變量的值都會被記住 # 第一次調用,外層函數的變量count=1, total=10.0, average=10.0 print(avg(10)) # 10.0 # 第二次調用,外層函數變量的值不會重置,仍然保持上次調用的結果 # 此時 count=2, total=30.0, average=15.0 print(avg(20)) # 15.0 # 第三次調用,外層函數變量的值仍然會保持上次調用的結果 # 此時 count=3, total=36.0, average=12.0 print(avg(6)) # 12.0
code
avg_cls = Averager()
當調用外層函數,返回內層函數對象時,即造成閉包。對象
avg(10)
每次對內層函數的調用,外層函數中的變量的值,都會被記住,即保持上次調用的結果。blog
若是不容易理解,能夠用類實例實現相似上面閉包的功能,實際執行中,由於類實例self的參與,運行速度要略慢於閉包的實現。it
# 以類實現相似上面閉包的功能 class Averager: def __init__(self): self.count = 0 self.total = 0.0 def __call__(self, value): self.total += value self.count += 1 average = self.total/self.count return average avg_cls = Averager() print(avg_cls(10)) # 10.0 print(avg_cls(20)) # 15.0 print(avg_cls(6)) # 12.0
class
閉包也是相似的效果,變量count和total也是存儲在外層函數的上下文中,因此每次對內層函數調用,外層函數的變量不會被銷燬,而是一直保持初始值(未調用內層函數時)或上次調用的結果(每次調用內層函數後,對count和total的修改都會被存儲)。變量