0

我在一个循环中多次执行一个动作,想知道我走了多远。我正在尝试制作一个进度报告功能,它应该像这样:

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

此代码不起作用。具体来说,我得到一个UnboundLocalErrorfor i。我应该如何修改它以使其正常工作?

4

4 回答 4

4

这里有 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. 使用nonlocal作为您的计数器(仅限 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
    
于 2013-03-17T21:22:34.120 回答
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)
于 2013-03-17T21:17:03.563 回答
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"
于 2013-03-17T21:01:08.097 回答
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

于 2013-03-17T21:22:21.450 回答