2011-01-19 10 views
110

私は次のように発電機能を持っている:ジェネレータからアイテムを1つだけ選択する方法(Pythonで)

def myfunct(): 
    ... 
    yield result 

この関数を呼び出すための通常の方法は、次のようになります。

for r in myfunct(): 
    dostuff(r) 

私の質問は、発電機からわずか1要素を取得する方法がありますいつでも好きですか? 例えば、私のような何かをしたいと思います:、アイテムを希望

g = myfunct() 

毎回を使用して発電機を作成

while True: 
    ... 
    if something: 
     my_element = pick_just_one_element(myfunct()) 
     dostuff(my_element) 
    ... 

答えて

161

を使用

g.next() 

または

next(g) 

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

next(g, default_value) 
+3

gの最後の項目が指定された後にg.next()を使用しようとすると、StopIterationが発生します。 – Wilduck

+15

'next(gen、default)'も、 'StopIteration'例外を避けるために使うことができます。たとえば、文字列のジェネレータの 'next(g、None)'は、繰り返しが終了した後に文字列またはNoneを生成します。 Python 3000の – Attila

+4

、next()は__next __()です。 –

-1

私は唯一の方法は、あなたはそのリストから目的の要素を取得するイテレータからリストを取得することであると信じています。

l = list(myfunct()) 
l[4] 
+0

Svenの答えはおそらくもっと良いですが、ここではあなたのニーズとよりインラインでそれを残しておきます。 – keegan3d

+22

これを行う前に有限のジェネレータがあることを確認してください。 – Seth

+5

申し訳ありませんが、これはイテレータの長さが複雑ですが、問題は明らかにO(1)です。 –

2

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

0
generator = myfunct() 
while True: 
    my_element = generator.next() 

(あなたの例によると、最後の要素がfor文で発電機の使用breakのただ一つの要素を選ぶため

+0

Python 3には無効です。優れた[answer by kxr](http://stackoverflow.com/a/35370041/260122)を参照してください。 – clacke

12

を取られた後にスローされた例外をキャッチしてください、またはlist(itertools.islice(gen, 1))

あなたは次のようにすることができます:

while True: 
    ... 
    if something: 
     for my_element in myfunct(): 
      dostuff(my_element) 
      break 
     else: 
      do_generator_empty() 

を取得するjusからTつの元素[一度生成]次に、発生器Iはをいつでも「(私は50元の意図厥%、および最も一般的な意図を想定):generator.next()の明示的な使用をすることができる

gen = myfunct() 
while True: 
    ... 
    if something: 
     for my_element in gen: 
      dostuff(my_element) 
      break 
     else: 
      do_generator_empty() 

この方法回避され、入力の終了処理では、(暗黙的に)例外処理や余分なデフォルト値の比較は不要です(StopIteration)。

else:forステートメントセクションは、ジェネレータの終了時に特別な処理をしたい場合にのみ必要です。next()/.next()

注:その考えローレベル(PEP 3114):のpython3で

.next()方法が良い理由.__next__()に改名されました。 Python 2.6より前の組み込み関数next()は存在しませんでした。また、next()operatorモジュール(これは賢明だったでしょう)に移動することについて議論されました。なぜなら、まれな必要性と組み込みの名前の不確かな膨張のためです。

デフォルトなしでnext()を使用すると、暗黙のうちに通常のアプリケーションコードの青色のボルトのように暗黙のうちに投げ込まれます。 next()を直接builtinsに入れる唯一のオプションでなければならないデフォルトのセンチネルを使ってnext()を使用することは限られており、しばしば奇妙な非平凡な論理/読みやすさの理由を与えます。

ボトムライン:operatorモジュールの機能のように、next()を使用するのは非常にまれです。 for x in iterator,islicelist(iterator)などの関数をイテレータをシームレスに受け入れることは、アプリケーションレベルでイテレータを使用する自然な方法です。 next()は、このスレッドの問題が示すように、低レベルの特別な概念です。例えば、 forbreakを使用することは従来通りです。

+0

これは、リスト結果の最初の要素を取得するにはあまりにも多くの作業が必要です。多くの場合、私は怠け者である必要はありませんが、py3では選択肢がありません。 'mySeq.head'に似たものはありませんか? – javadba

関連する問題