web-dev-qa-db-ja.com

リストよりもPythonジェネレータを優先する必要がありますか?

Pythonイテレータはメモリ効率が非常に高くなります。リストだけでなく、常にジェネレータを使用したほうがよいですか?どのような場合に、単純な配列を使用すべきですか?

たとえば、これの代わりに:

emails = [user.email for user in users]

私はこれを好むべきですか?:

emails = (user.email for user in users)

:「イテレータ」ではなく「ジェネレータ」を意味します。

8
nicholaides

ジェネレータの主な欠点は、一方向にしかトラバースできないことです。以前の値に戻ることはありません。それらを共有することもできません。それが簡単に説明できる場合もあれば、それが望ましい場合も多くありますが、そうでない場合も多くあります。たとえば、並べ替え。

そのため、大量のデータの初期処理段階で使用されるジェネレーターがよく見られ、サブセットにフィルター処理され、Nice形式にマップされると、永続的な具象データ構造に入れられます。さらに使用。そうすれば、メモリの割り当て、キャッシュミス、ガベージコレクションのコストを、すぐに捨ててしまう大きな中間配列に費やす必要がなくなります。

7
Karl Bielefeldt

イテレータがジェネレータと混同されています。

最初の例はリスト反復子式で、2番目の例はジェネレータ式です。主な違いは、ジェネレーターは、指定されたコレクションの各メンバーを(必要に応じて)即座にではなく(必要に応じて)遅延して作成することです。 returnではなくyieldを使用して、独自のジェネレーターを定義できます。

使用方法に関する限り、それ自体のためのリスト(または辞書など)が必要な場合は、イテレータが必要です。コレクションが最終製品に付随する場合は、ジェネレータを使用します。たとえば、ジェネレータを使用して、いくつかの他の基準からいくつかの基準を満たす数値のリストを取得できます。元のリストは気にせず、基準に一致するメンバーのみを対象とします。したがって、ジェネレータを使用してこれらの数値のみを取得します。

より具体的な例は、辺の長さが一定である三角形の角度を見つけることです。私たちはすべての貧しい、変形した三角形が必要なのではなく、強くて健康な三角形だけが欲しいです。したがって、ジェネレータを使用します。

このスタックオーバーフロー post はさらに詳しく説明します。

3
World Engineer