闭包
通俗地说,就是函数嵌套(后续称之为外层函数)另一个函数(后续称之为内层函数),在内层函数中,引用外层函数的变量,每次对内层函数的调用,外层函数变量的值都会进行保持。函数
用个简单的例子来讲明,使用闭包实现一个函数,求全部传入的数字的平均值。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的修改都会被存储)。变量