1. ホーム
  2. python

[解決済み] なぜnextは'StopIteration'を発生させるのに、'for'は通常のリターンを行うのでしょうか?

2022-03-06 22:03:44

質問

このコードでは、なぜ 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??

この場合、なぜトレースバックが表示されないのでしょうか?

解決方法は?

その for ループは StopIteration を明示的に指定します。

の目的は for 文は、イテレータが提供するシーケンスをループするもので、例外はイテレータが終了したことを通知するために使用されます。 for は、反復処理されているオブジェクトが発生させる他の例外をキャッチせず、この例外だけをキャッチします。

それは StopIteration は、反復処理をしている人に、これ以上生成するものがないことを伝えるための、通常、期待されるシグナルです。

ジェネレータ関数は、特殊なイテレータです。 StopIteration は、関数が終了したとき(つまり、戻ったとき、だから、はい。 return None レイズ StopIteration ). これはイテレータの要件であり、イテレータは しなければならない 上げる StopIteration を実行したときに、その結果を表示します。 StopIteration が発生した場合、そこから別の要素を取得しようとすると ( next() を呼び出すか、あるいは .next() (パイ2)または .__next__() (py 3) イテレータのメソッド) が必要です。 常に StopIteration をもう一度。

GeneratorExit での通信は例外です。 その他 の方向に移動します。あなたは、明示的に 終了 を持つジェネレータは yield 式で、Pythonがそのクロージャをジェネレータに伝える方法は GeneratorExit その関数の内部で の内部で明示的に例外をキャッチします。 countdown その目的は、ジェネレータが終了する際に、必要に応じてリソースをクリーンアップすることです。

A GeneratorExit は呼び出し元には伝搬されません。 generator.close() ドキュメント .