45

raise StopIterationusingとreturnジェネレーターのステートメントの違いに興味があります。

たとえば、これら 2 つの機能に違いはありますか?

def my_generator0(n):
    for i in range(n):
        yield i
        if i >= 5:
            return

def my_generator1(n):
    for i in range(n):
        yield i
        if i >= 5:
            raise StopIteration

より「pythonic」な方法は2番目の方法だと思いますが(間違っている場合は修正してください)、両方の方法でStopIteration例外が発生することがわかります。

4

3 に答える 3

52

明示的にレイズする必要はありません。これはStopIteration、生のreturnステートメントがジェネレーター関数に対して行うことなので、同じです。しかし、いいえ、使用するだけreturnでより Pythonic になります。

From: http://docs.python.org/2/reference/simple_stmts.html#the-return-statement (Python 3.2 で有効)

ジェネレーター関数では、return ステートメントに expression_list を含めることはできません。そのコンテキストでは、生のリターンはジェネレーターが完了したことを示し、StopIteration が発生します。

または @Bakuriu が指摘するように、Python 3.3 ではジェネレーターのセマンティクスがわずかに変更されているため、以下がより適切です。

ジェネレーター関数では、return ステートメントは、ジェネレーターが完了し、StopIteration が発生する原因となることを示します。戻り値 (存在する場合) は、StopIteration を構築するための引数として使用され、StopIteration.value 属性になります。

于 2013-01-06T15:56:44.023 に答える
24

2014 年後半の時点returnで正しくraise StopIteration、発電機を終了するには減価償却の予定です。詳細はPEP 479を参照してください。

概要

この PEP は、ジェネレーターへの変更を提案します: がStopIterationジェネレーター内で発生した場合、それは に置き換えられRuntimeErrorます。(より正確には、これはジェネレーターのスタック フレームから例外が発生しようとしているときに発生します。) 変更は下位互換性がないため、最初に__future__ステートメントを使用して機能が導入されます。

受け入れ

この PEP は 11 月 22 日に BDFL によって承認されました…</p>

根拠

ジェネレーターと StopIteration の相互作用は、現在のところやや驚くべきものであり、あいまいなバグを隠している可能性があります。予期しない例外により、動作が微妙に変更されることはありませんが、ノイズが多く、デバッグが容易なトレースバックが発生する必要があります。現在、ジェネレーター関数内で誤って発生した StopIteration は、ジェネレーターを駆動するループ構造による反復の終わりとして解釈されます。

…</p>

于 2015-05-13T14:23:40.743 に答える
5

確かに、一方が読み取り可能で他方が不明瞭であることを除いて、それらは同等です。これは、ジェネレーターの最初のバージョン (PEP 255、「仕様: リターン」の下) にまでさかのぼり、その後の (コルーチンなどの) 拡張はこれを変更しません。3.3 yield from(PEP 380)では、これをreturn <expr>のシンタックス シュガーとして拡張しraise StopIteration(<expr>)ていますが、 の意味は変わりませんreturn;

于 2013-01-06T16:00:16.687 に答える