2016-08-16 14 views
0

Pythonでは、ループ内の値を生成するジェネレータが、そのループの最終値が返される通常の関数として代わりに呼び出される可能性はありますか?私は引数としてフラグを設定して、そのフラグに応じて返すか返すかを選択しました。しかし、関数内にキーワードyieldが存在するだけで、それが自動的にジェネレータに変換され、Pythonはジェネレータにreturn文があると不満を持ちます。Pythonのハイブリッドジェネレータ/ファンクション

ここでは、そのような機能の例:

def function(generator=True): 
    a = 0 
    for i in range(10): 
     a = i 
     if generator: 
      yield a 
    if not generator: 
     return a 

いくつかのケースでは、私はちょうど(例えば、最適化のための残差の関数としてそれを使用。)最終的な結果を必要とするときにいる間、このような機能は私のために有用であろう他のケース私は、各反復後に増分結果が必要です(例えば、ロボットの差動モデルを使用して、新しい新しい速度コマンドでロボットの姿勢を更新するなど)。今のところ私は2つの機能を持っています.1つは歩留まりがあり、もう1つは戻ります。その2つを組み合わせることは可能ですか?

+0

重複して同じ結果を生成することを注意! http://stackoverflow.com/questions/26595895/return-and-yield-in-the-same-function –

+1

ジェネレータ全体を反復処理し、最後の結果を返すラッパーを作成しますか?同じ機能がジェネレータ*と*ノーマルファンクションの両方のように機能することは狂気のようです。その責任を分けたこれを言って、1つの値に対してジェネレータ全体を反復することはさらに賢明なようです。最後の値を直接計算することはできませんか?実際には、これら2つの関数の責任を分割しますか? – deceze

+0

私が知る限り、ロボットからのデータは周期的(65536に達するとゼロでリセット)され、ステップ更新を段階的に計算する必要があるモータエンコーダティックを表すので、それは不可能であるすべて。ラッパーはまだ別の関数なので、融合が可能かどうか疑問に思っていました。そして、狂気は常に悪い言葉ではありません:) – Mehdi

答えて

1

これはまだジェネレータであり、リターンを呼び出しています。 とにかくジェネレータ/レギュラーの両方の機能を混在させたくありません。

とにかく結果をループする必要がある場合に備えて、イテレータの上に何かをラップすることができます。

あなたがやりたいことができ、簡単なコード:

last = None 
for last in function(): pass 

今、最後の希望の値を保持し、あなたのコードでそれを使用することができます。

発電機内部のリターンは Python 3.3 に添加し、そしてそれは、呼び出すとStopIteration(値)と等価です

return expr in a generator causes StopIteration(expr) to be raised upon exit from the generator.

In a generator, the statement

return value is semantically equivalent to

raise StopIteration(value) except that, as currently, the exception cannot be caught by except clauses within the returning generator.

+0

提案された質問でも重複として、人々はリターンが発電機の中で呼び出すことができると言うが、私の場合はそれが私のプログラムをクラッシュさせる。 SyntaxError:ジェネレータ内の引数を含む 'return' – Mehdi

+0

ジェネレータ内の「戻り値」がPython 3.3に追加されたようです。https://www.python.org/dev/peps/pep-0380/#use-of-stopiteration戻り値 あなたはどのバージョンを使用していますか? – danielfranca

+0

私は使用しているPython 2.7で値を返すことはできません。 – Mehdi

1

あなたはまだその単一の値を取得するには、それを反復処理する必要がありますが、あなたは再びyieldを使用することができますこれを達成するためにreturnの代わりに。

>>> def function(generator=True): 
...  a = 0 
...  for i in range(10): 
...   a = i 
...   if generator: 
...    yield a 
...  if not generator: 
...   yield a 
... 
>>> a = function() 
>>> print(*a) 
0 1 2 3 4 5 6 7 8 9 
>>> a = function(0) 
>>> print(a) 
<generator object function at 0x0000000001603240> 
>>> print(*a) 
9 
>>> a = function(0) 

ジェネレータ内部returnは、Python 2でSyntaxErrorあるが、パイソン3. yieldreturnを交換しない有する2および3

+0

アンパックするのではなく、単に 'next':' val = next(function(False)) 'を呼び出すこともできます。 – Bakuriu

+0

@Bakuriu - 私はそれを考えましたが、短くて怠けているので '* 'と一緒に行きました。 :P – TigerhawkT3