1. ホーム
  2. python

[解決済み] Pythonジェネレータを使うのにふさわしくないのはいつですか?

2023-04-21 04:55:16

質問

これは、むしろ Pythonのジェネレータ関数は何のために使うことができますか? : Python ジェネレータ、ジェネレータ式、そして itertools モジュールは、最近のPythonのお気に入りの機能の一部です。特に、大量のデータに対して実行する一連の操作を設定するときに便利で、私はDSVファイルを処理するときによく使用します。

では、いつ ではない を使うのは良いタイミングなのでしょうか? itertools 関数を使うか?

  • どのような場合に zip() よりも itertools.izip() または
  • range() 以上 xrange() または
  • [x for x in foo] 以上 (x for x in foo) ?

もちろん、最終的にはジェネレーターを実際のデータに解決する必要があります。通常はリストを作成するか、ジェネレーター以外のループで反復処理します。時には、長さを知る必要がある場合もあります。これは私が尋ねていることではありません。

ジェネレータを使うのは、中間データ用に新しいリストをメモリに割り当てないようにするためです。これは特に大きなデータセットに対して意味があります。小規模なデータセットでも意味があるのでしょうか。メモリと CPU のトレードオフは顕著ですか?

の目を見張るような議論に照らして、誰かがこれに関していくつかのプロファイリングを行ったなら、私は特に興味を持ちました。 リスト内包のパフォーマンス vs. map() および filter() . ( altリンク )

どのように解決するのですか?

ジェネレータの代わりにリストを使用する場合。

1) データにアクセスする必要がある 複数 回アクセスする必要がある (つまり、再計算する代わりに結果をキャッシュする)。

for i in outer:           # used once, okay to be a generator or return a list
    for j in inner:       # used multiple times, reusing a list is better
         ...

2) 必要なのは ランダムアクセス (または前方順序以外のアクセス) が必要です。

for i in reversed(data): ...     # generators aren't reversible

s[i], s[j] = s[j], s[i]          # generators aren't indexable

3) あなたは 参加する 文字列を結合する必要があります (これはデータに対して 2 回のパスを必要とします)。

s = ''.join(data)                # lists are faster than generators in this use case

4) あなたは PyPy を使っていて、通常の関数呼び出しやリスト操作と同じようにジェネレータコードを最適化できないことがある。