1

次のコードで正確に何が起こるかわかりません。

def coroutine():
    lst = []
    try:
        while True:
            item = (yield lst)
            if item == 3:
                raise ValueError
            print('append {}'.format(item))
            lst.append(item)
    except GeneratorExit:
        print('GeneratorExit')

crt = coroutine()

next(crt)
print(crt.send(1))
print(crt.send(2))

try:
    print(crt.send(3))
except ValueError:
    pass

print(crt.send(4))

これは以下を出力します:

append 1
[1]
append 2
[1, 2]

Traceback (most recent call last):
  File "D:\Documents and Settings\Brecht\Desktop\crt.py", line 25, in <module>
    print(crt.send(4))
StopIteration

デバッガーでコードをステップraise ValueError実行すると、実行は にジャンプしますexcept GeneratorExit:が、この except 節の本体は実行されません (「GeneratorExit」は出力されません)。なぜだめですか?

それを除けば、例外がスローされた後、コルーチンを再開できるとは思いませんか? これを許可しない特別な理由はありますか? これは、少なくとも私の特定のユースケースでは役立ちます:)

4

1 に答える 1

4

例外をスローすると、コード フローは常に中断されます。例外をスローすると、中断されたジェネレーターを再開することはできません。

PEP 342 (強化されたジェネレーターによるコルーチン)から:

next()メソッドと同様に、このsend()メソッドは、ジェネレーター イテレーターによって生成された次の値を返すStopIterationか、ジェネレーターが正常に終了した場合、または既に終了している場合に発生します。ジェネレーターがキャッチされていない例外を発生させた場合、それはsend()の呼び出し元に伝搬されます。

行にジャンプするデバッガーに関してはexcept、例外がスローされ、インタープリターは例外がその行でキャッチされるかどうかをテストしています。のみをキャッチするためGeneratorExit、ジェネレーターはその時点で終了します。

于 2013-03-12T21:03:13.320 に答える