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

したがって、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 のクロージャには項目が 1 つしかないことに気付くでしょう。これは、最初に に渡した値ですn。値はクロージャーのi一部ではないため、関数定義の外側はiスコープ外になります。

Python でのクロージャに関する素晴らしい議論があります: http://www.shutupandship.com/2012/01/python-closures-explained.html

于 2013-03-17T21:22:21.450 に答える
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 に答える