假设我们需要一个函数,用于计算平均值,每次调用这个函数时,都会把传入的入参保存在内部。
根据要求,这个函数的一种实现方式是使用装饰性函数,其内部使用闭包来存放次数与总量。最后再使用这两个数计算出平均值。
实现代码为:
def make_averager():
count = 0
total = 0
def averager(new_value):
count += 1
total += new_value
logging.debug('count -> %s',count)
logging.debug('total -> %s',total)
return total / count
return averager
if __name__ == '__main__':
avg = make_averager()
result = avg(10)
result = avg(11)
result = avg(12)
logging.info('result -> %s', result)
运行结果:
IDE 也提醒我们这里的 count 与 total 变量存在问题:
因为对于数字、字符串、元组等不可变类型来说,它们只能读取,不能更新。 如果对其更新,比如示例中的 count += 1,就会隐式地创建局部变量 count。这样,count 这个变量就不是自由变量了,所以也就不会被保存在闭包中。
Python 3 引入了 nonlocal 声明,就是为了解决这一问题。它的作用是把可能引起上述问题的变量标记为自由变量,这样也就可以使用闭包来保存值咯。
上述代码进行简单修改即可:
运行结果:
Luciano Ramalho (作者),安道,吴珂 (译者).流畅的Python[M].人民邮电出版社,2017:316-318.
网友评论