次のようなジェネレーター関数があります。
def myfunct():
...
yield result
この関数を呼び出す通常の方法は次のとおりです。
for r in myfunct():
dostuff(r)
私の質問、私が好きなときにいつでもジェネレータから1つの要素を取得する方法はありますか?たとえば、私は次のようなことをしたいです:
while True:
...
if something:
my_element = pick_just_one_element(myfunct())
dostuff(my_element)
...
を使用してジェネレーターを作成する
g = myfunct()
アイテムが欲しいときはいつでも
next(g)
(またはPython 2.5以下のg.next()
)。
ジェネレーターが終了すると、StopIteration
が発生します。必要に応じてこの例外をキャッチするか、next()
にdefault
引数を使用できます。
next(g, default_value)
ジェネレーターの要素を1つだけ選択するには、break
ステートメントでfor
を使用するか、list(itertools.islice(gen, 1))
を使用します
あなたの例によれば(文字通り)あなたは次のようにすることができます:
while True:
...
if something:
for my_element in myfunct():
dostuff(my_element)
break
else:
do_generator_empty()
「から1つの要素のみを取得 [一度生成] 好きなときはいつでもジェネレーター」(50%が元の意図であり、最も一般的な意図であると仮定する) :
gen = myfunct()
while True:
...
if something:
for my_element in gen:
dostuff(my_element)
break
else:
do_generator_empty()
このようにgenerator.next()
の明示的な使用を避けることができ、入力終了処理では(暗号化)StopIteration
例外処理または追加のデフォルト値の比較を必要としません。
else:
of for
ステートメントセクションは、発電機終了の場合に何か特別なことをしたい場合にのみ必要です。
next()
/.next()
に関する注意:Python3では、.next()
メソッドの名前が.__next__()
に変更されました。これには正当な理由があります。低レベルと見なされます(PEP 3114)。 Python 2.6より前では、組み込み関数next()
は存在しませんでした。また、next()
をoperator
モジュールに移動すること(それは賢明だったはずです)が、組み込み名のまれな必要性と疑わしいインフレーションのために議論されました。
next()
をデフォルトなしで使用することは、依然として非常に低レベルのプラクティスです。通常のアプリケーションコードでは、隠されたStopIteration
をボルトのように放り出します。また、next()
をデフォルトのセンチネルで使用することは、builtins
で直接next()
の唯一のオプションである必要があります-制限され、多くの場合、奇妙な非Pythonロジック/可読性の理由を示します。
結論:next()を使用することは非常にまれです-operator
モジュールの関数を使用するように。 for x in iterator
、islice
、list(iterator)
、およびイテレータをシームレスに受け入れる他の関数を使用することは、アプリケーションレベルでイテレータを使用する自然な方法であり、常に可能です。 next()
は低レベルであり、余分な概念であり、明白ではありません-このスレッドの質問が示すように。たとえばbreak
でfor
を使用することは従来どおりです。
ジェネレータから任意の値を取得する便利な方法があるとは思わない。ジェネレータはnext()メソッドを提供して自身を走査しますが、メモリを節約するために完全なシーケンスはすぐには生成されません。それがジェネレータとリストの機能的な違いです。
generator = myfunct()
while True:
my_element = generator.next()
最後の要素が取得された後にスローされた例外を必ずキャッチしてください