質問

特定のフィルターに一致するリスト内の項目の数を数える最も簡単な方法を見つけようとしていました。この場合、リスト内に奇数がいくつあるかを調べます。

これを実行しているときに、リスト内包表記と同等のジェネレーター式を比較した結果に驚きました。

python -m timeit -s "L = xrange(1000000)" "sum([1 for i in L if i & 1])"
10 loops, best of 3: 109 msec per loop

python -m timeit -s "L = xrange(1000000)" "sum(1 for i in L if i & 1)"
10 loops, best of 3: 125 msec per loop

L が通常のリストであり、さまざまなサイズでも試してみましたが、いずれの場合もリストの内包性が優先されます。

100 万個の項目を含む新しいリストを作成する listcomp と比較して遅い原因となる genexp は何をしているのでしょうか...?

(ちなみに、私が見つけた最も速い方法は次のとおりです: x = 1; len(filter(x.__and__, L)). 。そして、はい、そのようなコードを書くと子猫が死ぬことは知っています、私はそれを楽しむためにやっています)

役に立ちましたか?

解決

基本的に無制限のメモリが利用可能である場合 (実際の問題ではそうでないこともよくありますが、小さなベンチマークでは常にそうなります!)、リストは 1 つの「大きな束」で 1 回だけ割り当てられるため、ジェネレーターよりも優れたパフォーマンスを発揮する傾向があります (メモリの断片化などはありません)。一方、ジェネレータはスタック フレームの状態を保持して実行を再開できるようにすることで、「大きな束」アプローチを回避するために (内部で) 特別な努力を必要とします。

リストアプローチとジェネレーターアプローチのどちらが速いか 実際のプログラムでは 断片化などの正確なメモリ状況に依存しますが、「マイクロベンチマーク」で正確に再現することはほぼ不可能です。結局のところ、本当にパフォーマンスを重視するのであれば、一般的な「おもちゃの」マイクロ ベンチマークではなく、実際のプログラムを慎重にベンチマークする (そして、別途プロファイリングする) 必要があります。

他のヒント

これを試してみてください:

function draw(id, clr, fill) {  
      var canvas = document.getElementById(id);  
      if (canvas.getContext) {  
        var ctx = canvas.getContext("2d");  

        ctx.fillStyle = clr;  
        ctx.fillRect (fill);  

      }  
    }
.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top