5

私はメソッドを持つオブジェクトのリストを持っています。たとえばcleanup()、それらすべてに対して呼び出す必要があります。少なくとも 2 つの方法があることを理解しています。

map(lambda x: x.cleanup(), _my_list_of_objects)

また

for x in _my_list_of_objects:
    x.cleanup()

私の質問:

  1. 一方は他方より Pythonic ですか?
  2. 他に良い方法はありますか?ここでは前者が (作業中の) コード ベースで頻繁に使用されているのを目にしますが、map が構築してリストを返し、それが破棄されることに悩まされています (そうですか?)。
  3. (すぐに GC されるリストの) パフォーマンスへの影響は考慮すべきものですか?
4

3 に答える 3

7

map、リスト内包表記、ジェネレーター式、または n 値にいくつかの操作を適用して結果を収集するその他のものを副作用のために使用することは慣用的ではありません。関数型プログラミングの概念が適用されない場合 (つまり、不純なコード) で関数型プログラミングの概念を使用することを主張したとしても、実際的な懸念事項があります。

  • n 個の参照 (ほとんどの場合 ) を蓄積するメモリと計算が無駄になり、Noneその後すぐに破棄されます。
  • Python 3mapは怠惰なので、Python 3 に移植すると (特に 2to3 を避ける場合 - 十分な理由があります) 、このコードは黙って動作を停止します。
  • ポイント1だけでなく、おそらく遅くなります。mapすべての要素に対して完全な関数呼び出しを実行する必要があり、明示的なループはバイトコードレベルで1回のジャンプのみを必要とします。リスト内包表記は AFAICT を必要としませんが、timeit.

iterable のすべての要素に対して何かをしたい場合、まさにそれループ目的forです。簡潔でシンプル。これ以上読みやすくなることはありません。場合によっては、特定の Python 実装ではよりあいまいなバリアントの方が高速になる可能性がありますが、読みやすさを犠牲にする価値は事実上ありません (そして、それが実際に勝っていることを確認する時間です!)。

于 2013-10-09T20:34:36.300 に答える
6
  1. for結果を気にしないという理由だけで、 -loop ソリューションの方が優れていますcleanupPython の機能mapサブセットの一部です。これを使用して副作用を作成するのは、使用方法としては不適切です。

    またmap、(リストを作成するため)python2のスペースを浪費し、反復可能オブジェクトを消費する必要があるpython3では機能しないことに注意してください。python3 では、次のようなものがあります。

    from collections import deque
    deque(map(function, iterable), maxlen=0)
    

    スペースのオーバーヘッドなしで関数を呼び出すためです。これにより、ループのfor読みやすさが大幅に失われると思います。for-loop ソリューションは、どのバージョンの Pythonでも機能します。

  2. これを行うには多くの方法がありますが、for-loop ほど読みやすく、パフォーマンスに大きなメリットをもたらすものはありません。

  3. リストのサイズと特定の状況によって異なります。コードがタイトなループにある場合、大きな影響を与える可能性があります。ただし、Python は小さなオブジェクトを処理するように高度に最適化されているため、要素の数が少ない場合、OS によってメモリ割り当てが実際に実行されることはありません。

于 2013-10-09T20:33:50.233 に答える
0

そのため、「リスト内の一連のオブジェクトでこの関数を呼び出す」の省略形として map() を使用しています。結局のところ、リスト内包表記は (通常) ループ内で同じことを行うよりも高速です。

とにかく、ここに結果があります:

r = [[] for _ in range(10000)]
%timeit map(lambda y: r[y].append(1), x)
100 loops, best of 3: 2.56 ms per loop

r = [[] for _ in range(10000)]
%%timeit
for y in x:
    r[y].append(1)
1000 loops, best of 3: 1.67 ms per loop

この場合、閉じさえしません。 for ループ メソッドは約 2 倍高速です。

于 2013-10-10T04:09:57.247 に答える