85

このコードでは、使用するとfor結果が発生しないのはなぜですかStopIteration 、またはforループがすべての例外をトラップしてからサイレントに終了するのですか?その場合、なぜ私たちは無関係なのですreturnか?または、次の raise StopIteration原因によるものですreturn Noneか?

#!/usr/bin/python3.1
def countdown(n):
    print("counting down")
    while n >= 9:
        yield n
        n -= 1
    return

for x in countdown(10):
    print(x)

c = countdown(10)
next(c)
next(c)
next(c)

StopIterationによってトリガーされていると仮定しますreturn None。いつGeneratorExit生成されますか?

def countdown(n):
    print("Counting down from %d" % n)
    try:
        while n > 0:
            yield n
            n = n - 1
    except GeneratorExit:
        print("Only made it to %d" % n)

手動で行う場合:

c = countdown(10)
c.close() #generates GeneratorExit??

その場合、なぜトレースバックが表示されないのですか?

4

1 に答える 1

108

ループは明示的にforリッスンします。StopIteration

ステートメントの目的はfor、イテレーターによって提供されたシーケンスをループすることであり、例外は、イテレーターが完了したことを通知するために使用されます。for繰り返されるオブジェクトによって発生する他の例外をキャッチしません。その例外だけをキャッチします。

これStopIterationは、反復している人に、これ以上生成されるものがないことを通知する、通常の予想される信号だからです。

ジェネレーター関数は特別な種類のイテレーターです。関数が実行されたときに実際に発生StopIterationします(つまり、関数が戻ったときに発生するので、そうです、return None発生しますStopIteration)。これはイテレータの要件です。終わったらレイズしなければなりませんStopIteration。実際、aStopIterationが発生すると、それらから別の要素を取得しようとすると(を介して、またはイテレータで(py 2)または(py 3)メソッドをnext()呼び出す)、常に再度発生する必要があります。.next().__next__()StopIteration

GeneratorExit反対方向に通信する場合の例外です。式を使用してジェネレーターを明示的に閉じyieldています。Pythonがそのクロージャーをジェネレーターに伝達する方法はGeneratorExit、その関数の内部を上げることです。の内部でその例外を明示的にキャッチしますcountdown。その目的は、ジェネレータが閉じるときに必要に応じてリソースをクリーンアップできるようにすることです。

AGeneratorExitは呼び出し元に伝播されません。generator.close()ドキュメントを参照してください。

于 2013-01-19T11:46:14.343 に答える