一段关于python 闭包的例子
>>> def counter(a=0): ... count = a ... def incr(): ... b = 1 + count ... return b ... return incr ... >>> count = counter(5) >>> print count() 6 >>> print count() 6 >>> >>> def counter(start_at=0): ... count = [start_at] ... def incr(): ... count[0] += 1 ... return count[0] ... return incr ... >>> count = counter(5) >>> print count() 6 >>> print count() 7 >>> print count() 8 >>>
有若干疑点不懂。 列出来一一解惑
1. 第二段代码的function counter 在内部定义了一个function incr。这个incr被当做返回值返回。 我们用count 去接受这个返回值然后每次调用的时候 print count() 会得到累加的结果6, 7 , 8. 但是这个累加值的变量应该是定义在counter()这个外层函数中的啊。 以我的理解外层函数结束了,其定义的变量应该也不可访问了。为什么count函数可以不断的访问并累加这个值呢?
这是因为python中对变量的访问都是引用。外层函数生成了一个变量,内层函数count又对这个变量引用了一次。只要内层函数对这个变量的引用还在,这个变量就不会被销毁,就仍然可用。 我所理解的外层函数退出,变量就不可以再访问其实是因为我潜意识里认为外层函数退出,变量的引用就结束了。然而在这个例子中变量的引用并没有结束,所以仍然存在并且可以访问。
2. 对于第二段代码,我们知道它返回一个函数调用。那么也就是说counter()类似于一个函数名。而我们用counter()()就应该是这个函数调用。 我们看一下执行,
>>> counter()() 1 >>> counter()() 1
确实是函数调用,但是为什么不是像print count()这种累加呢?
这是因为,counter()每次运行生成一个新的函数对象并返回。如下所示:
>>> counter() <function incr at 0xe10c848> >>> counter() <function incr at 0xe10ca28> >>>
所以 counter()()每次都相当于第一次执行。每次是在执行不同的函数instance。 而 count=counter() print count()这种方式则不然。 这种方式是执行一次counter()以后把返回的函数调用保存在一个变量也就是count中形成了一次引用。以后每次调用print count()都是对这同一个函数调用。