python nonloacal

时间:2023-03-09 13:43:08
python nonloacal

Python 3 添加了 nonlocal 关键字,把 None、True 和 False 提升为关键字,废弃了 print 和 exec。今天细说下 nonlocal 的用法

  nonloacal是最近出现的保留关键字,在python3.0中引入。如果想自己实现函数装饰器,那就必须了解闭包的方方面面,因此也就需要知道nonloacal。

  题外话:闭包除了在装饰器中有用处之外,还是回调式异步编程和函数时编程风格的基础。

这里借用《流畅的python》一书中的例子来说明下:

def make_averager():
count = 0
total = 0 def averager(new_value):
count += 1
total += new_value
return total / count return averager

调用执行,会得到如下结果:

>>> avg = make_averager()
>>> avg(10)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 6, in averager
UnboundLocalError: local variable 'count' referenced before assignment

  问题是,当count是数字或任何不可变类型时,count += 1 语句的作用其实与count = count + 1一样。因此,我们在 averager 的定义体中为 count 赋值了,这会把 count 变成局部变量。total 变量也受这个问题影响。

  对于不可变类型来说,只能读取,不能更新,如果尝试重新绑定,例如count = count + 1,其实会隐式创建局部变量 count。这样,count 就不是*变量了,因此不会保存在闭包中。

  为了解决这个问题,Python 3 引入了 nonlocal 声明。它的作用是把变量标记为*变量,即使在函数中为变量赋予新值了,也会变成*变量。如果为 nonlocal 声明的变量赋予新值,闭包中保存的绑定会更新,更新后的版本如下:

def make_averager():
count = 0
total = 0
def averager(new_value):
nonlocal count, total
count += 1
total += new_value
return total / count
return averager

  在python2中没有nonlocal的情况下问题是怎么解决的呢?http://www.python.org/dev/peps/pep-3104/中的第三个代码片段给出了一种方法。基本上,这种处理方式是把内部函数需要修改的变量(如 count 和 total)存储为可变对象(如字典或简单的实例)的元素或属性,并且把那个对象绑定给一个*变量。