一个同事最近在看廖雪峰老师的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引用,它们所占的内存空间不会被释放。这样就延长了变量的生命周期。

参考:

results matching ""

    No results matching ""