Python中的闭包 - 一个例子

时间:2013-03-17 20:13:27

标签: python closures

我在循环中多次执行一个动作,想知道我有多远。我正在尝试制作一个应该采取以下行为的进度报告功能:

def make_progress_report(n):
    i = 0
    def progress_report():
        i = i + 1
        if i % n == 0:
            print i
    return progress_report

pr = make_progress_report(2)
pr()
pr()  # 2
pr()
pr()  # 4

此代码不起作用。具体来说,我为UnboundLocalError获得i。我应该如何修改它以使其有效?

4 个答案:

答案 0 :(得分:3)

以下是3个选项:

  1. 使用您的柜台清单:

    def make_progress_report(n):
        i = [0]
        def progress_report():
            i[0] = i[0] + 1
            if i[0] % n == 0:
                print i[0]
        return progress_report
    
  2. 使用itertools.count跟踪您的计数器:

    from itertools import count
    def make_progress_report(n):
        i = count(1)
        def progress_report():
            cur = i.next()
            if cur % n == 0:
                print cur
        return progress_report
    
  3. 非本地用于您的计数器(仅限Python 3+):

    def make_progress_report(n):
        i = 0
        def progress_report():
            nonlocal i
            i = i + 1
            if i % n == 0:
                print i
        return progress_report
    

答案 1 :(得分:2)

您可以考虑使用生成器:

def progress_report(n):
    i = 0
    while 1:
        i = i+1
        if i % n == 0:
            print i
        yield # continue from here next time

pr = progress_report(2)

next(pr)
next(pr)
next(pr)
next(pr)

答案 2 :(得分:0)

再看看你如何定义你的闭包。在定义闭包时应该传入n ...采用以下示例:

#!/usr/env python
def progressReportGenerator(n):
    def returnProgress(x):
        if x%n == 0:
            print "progress: %i" % x
    return returnProgress

complete = False
i = 0 # counter
n = 2 # we want a progress report every 2 steps

getProgress = progressReportGenerator(n)

while not complete:
    i+=1 # increment step counter

    # your task code goes here..

    getProgress(i) # how are we going?

    if i == 20: # stop at some arbtirary point... 
        complete = True
        print "task completed"

答案 3 :(得分:0)

所以progress_report没有关闭变量i。你可以这样检查......

>>> def make_progress_report(n):
...     i=0
...     def progress_report():
...             i += 1
...             if i % n == 0:
...                     print i
...     return progress_report
...
>>> pr = make_progress_report(2)
>>> pr.__closure__
(<cell at 0x1004a5be8: int object at 0x100311ae0>,)
>>> pr.__closure__[0].cell_contents
2

你会注意到pr的关闭中只有一个项目。这是您最初传递给n的值。 i值不是闭包的一部分,因此在函数定义之外,i不再在范围内。

以下是关于Python中闭包的一个很好的讨论:http://www.shutupandship.com/2012/01/python-closures-explained.html