2.6の集合の内包性を試していたところ、次の2つの方法に出くわしました。最初の方法は2番目の方法よりも速いと思いましたが、timeit
そうでない場合は提案されました。2番目のメソッドに追加のリストのインスタンス化とそれに続くセットのインスタンス化があるのに、なぜ2番目のメソッドの方が速いのですか?
方法1:
In [16]: %timeit set(node[0] for node in pwnodes if node[1].get('pm'))
1000000 loops, best of 3: 568 ns per loop
方法2:
In [17]: %timeit set([node[0] for node in pwnodes if node[1].get('pm')])
1000000 loops, best of 3: 469 ns per loop
ここでpwnodes = [('e1', dict(pm=1, wired=1)), ('e2', dict(pm=1, wired=1))]
。
リスト内包表記を使用すると、反復が単純に高速になります。
In [23]: from collections import deque
In [24]: %timeit deque((node[0] for node in pwnodes if node[1].get('pm')), maxlen=0)
1000 loops, best of 3: 305 µs per loop
In [25]: %timeit deque([node[0] for node in pwnodes if node[1].get('pm')], maxlen=0)
1000 loops, best of 3: 246 µs per loop
deque
反復速度を示すために使用されます。deque
withは、反復可能オブジェクトから取得されたすべての要素maxlen
を0
破棄するように設定されているため、結果を歪めるためのメモリ割り当ての違いはありません。
これは、Python 2では、リスト内包表記が個別の名前空間を使用しないのに対し、ジェネレーター式は使用するためです(必然的に使用する必要があります)。その余分な名前空間はスタック上に新しいフレームを必要とし、これはコストがかかります。ジェネレータ式の主な利点は、速度ではなく、メモリフットプリントが低いことです。
Python 3では、リスト内包には別の名前空間もあり、リスト内包とジェネレーターの反復速度は同等です。また、Python 2でも最速の内包表記を設定しましたが、
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加