一段关于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()都是对这同一个函数调用。

 

 

posted on 2014-04-17 17:51  kramer  阅读(345)  评论(0编辑  收藏  举报

导航