web-dev-qa-db-ja.com

(Pythonで)ジェネレータから1つのアイテムを選択する方法は?

次のようなジェネレーター関数があります。

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)
  ...
182
Alexandros

を使用してジェネレーターを作成する

g = myfunct()

アイテムが欲しいときはいつでも

next(g)

(またはPython 2.5以下のg.next())。

ジェネレーターが終了すると、StopIterationが発生します。必要に応じてこの例外をキャッチするか、next()default引数を使用できます。

next(g, default_value)
260
Sven Marnach

ジェネレーターの要素を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 iteratorislicelist(iterator)、およびイテレータをシームレスに受け入れる他の関数を使用することは、アプリケーションレベルでイテレータを使用する自然な方法であり、常に可能です。 next()は低レベルであり、余分な概念であり、明白ではありません-このスレッドの質問が示すように。たとえばbreakforを使用することは従来どおりです。

28
kxr

ジェネレータから任意の値を取得する便利な方法があるとは思わない。ジェネレータはnext()メソッドを提供して自身を走査しますが、メモリを節約するために完全なシーケンスはすぐには生成されません。それがジェネレータとリストの機能的な違いです。

2
g.d.d.c
generator = myfunct()
while True:
   my_element = generator.next()

最後の要素が取得された後にスローされた例外を必ずキャッチしてください

0
John