web-dev-qa-db-ja.com

いつジェネレーターを使用し、いつPythonでリストを使用すればよいですか?

多くの場合、リストを返すよりもジェネレータを記述する方がわかりやすいと思います。たとえば、私は好む

_def my_func_gen(foo):
    for i in foo:
        # Do some stuff that's too complicated for a list or generator comprehension
        yield whatever
_

_def my_func_list(foo):
    result = []
    for i in foo:
        # Do some stuff that's too complicated for a list or generator comprehension
        result.append(whatever)
    return result
_

さらに、 この答え は、「すべてに対してイテレータを使用することをお勧めします」と述べています。では、_my_func_gen_の方が優れているでしょうか。そうでないかもしれない。呼び出し元がリストを取得しているかイテレータを取得しているかさえわからないようにしたいのですが。しかし、たとえば、イテレータはPythonのNice Clean構文を使用してスライスできないため、呼び出し元はそれについて考える必要があります。 _itertools.islice_を使用する必要があります。

だから私は何をすべきですか?

  1. 「すべてにイテレータを使用する」というアドバイスは無視してください
  2. すべてのイテラブルでは使用できないスライスやその他の動作を使用する習慣をなくす
  3. list(my_iterable)を実行します。サポートをリストし、ジェネレーターがリストしない機能を使用したい場合はいつでも
  4. 時にはリストを使用し、その他にはジェネレータを使用します。でもいつ?

関連: here's イテレータをスライス可能にするためにラッパークラスを使用するコード。しかし、それはあなたが思うような方法では機能しません。_foo[:2]_を検索し、次に_foo[:2]_を検索すると、異なる結果が得られます。

6
kuzzooroo

ジェネレータとイテレータの間で混乱しています。それらはまったく同じ概念ではありません。

イテレータはPythonの優れたユビキタスです。あなたはそれらをたくさん使うべきです。 my_func_genとmy_func_listはどちらもこれらを使用します。

ジェネレータは、イテラブルを作成するための遅延方法です。これらは、完全に実現されたリストがメモリに収まらない場合、または各リスト要素を計算するコストが高く、できるだけ遅く実行したい場合に役立ちます。しかし、それらは一度しか反復できません。

this をご覧ください。

5
Pierre