一个同事最近在看廖雪峰老师的Python教程,今天突然问我如何使用闭包实现一个计数器,每调用一次,变量值自动加1。
我打开一个IPython终端(Python2.7.14环境),捣鼓了很久,终于给写出来了。
In [2]: def f1():
...: l1 = [0]
...: def f2():
...: l1[0] += 1
...: return l1[0]
...: return f2
...:
In [3]: m = f1()
In [4]: m()
Out[4]: 1
In [5]: m()
Out[5]: 2
In [6]: m()
Out[6]: 3
如果将f1函数中的变量l1=[0]换成i=0,将f2函数中的l1[0]换成i,会提示"UnboundLocalError: local variable 'i' referenced before assignment"报错,因为LEGB规则将f2函数中的变量i当作一个局部变量,不能在赋值前,使用它进行自增计算。
如果在Python3环境,使用nonlocal关键字,这样写则不会报错。
>>> def f1():
i = 0
def f2():
nonlocal i
i += 1
return i
return f2
>>> m = f1()
>>> m()
1
>>> m()
2
>>> m()
3
>>>
函数f2就是一个闭包,在上面的两个例子中,它分别包含了l1和i变量,l1和i变量都是在上一层函数f1里面定义的,即使f1函数生命周期结束,由于l1和i被f2引用,它们所占的内存空间不会被释放。这样就延长了变量的生命周期。
参考: