说说 Python 中 nonlocal 的作用

假设我们需要一个函数,用于计算平均值,每次调用这个函数时,都会把传入的入参保存在内部。
根据要求,这个函数的一种实现方式是使用装饰性函数,其内部使用闭包来存放次数与总量。最后再使用这两个数计算出平均值。

实现代码为:

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.

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 字符串格式化调用方法 —— format 通过创建字符串模板,利用format函数,替代相应的值。 可以通过绝对位...
    plutoese阅读 1,557评论 0 47
  • 闭包不好理解,所以先从示例说起。 假设我们需要计算平均值,这些值会从外层传递进来,然后被保存在内部。 (1) 非闭...
    deniro阅读 414评论 0 6
  • 下载地址:https://pan.baidu.com/s/1TrNBQL8VqUf6Yd41idVXXA[http...
    Secret_809b阅读 663评论 0 0
  • 先来看一个示例: 运行结果: 因为 b 没有定义,所以在运行 f1() 函数时抛错了。 在 pycharm 中也会...
    deniro阅读 358评论 0 4
  • 今天感恩节哎,感谢一直在我身边的亲朋好友。感恩相遇!感恩不离不弃。 中午开了第一次的党会,身份的转变要...
    迷月闪星情阅读 10,620评论 0 11