5

インターラブルで実行filterしていて、結果をシーケンスに格納したい(シーケンスを使用できるようにするためにシーケンスが必要ですrandom.choice)。フィルタオブジェクトからセットを作成する方が、リストタプルを作成するよりもはるかに高速であることに気付きました。何故ですか?最初に、フィルタータイプはセットのサブタイプであり、これを説明しますが、関数は実際にはジェネレーター式と同じであるため、実際には内部でセットにすることはできません。filter

速度を確認するために次のテストを実行しました。

import time

def test ( n, seq ):
    for method in ( set, list, tuple ):
        t = time.time()
        for i in range( n ):
            method( seq )
        print( method.__name__, ( time.time() - t ) )

someFilter = filter( lambda x: x % 3 == 0, range( 1000 ) )
test( 10000000, someFilter )

そして、結果はセットを使用するために明確に話していました:

set 1.9240000247955322
list 8.82200002670288
tuple 7.031999826431274

では、なぜフィルターからセットを作成する方がはるかに速いのでしょうか。通常、すべての要素をハッシュする必要があるシーケンスからセットを作成するのと同じくらい時間がかかるべきではありませんか?それとも、内部フィルター表現から何らかの形で後押しを得ているのでしょうか?

比較のために、range式でテストを実行する場合、とのset約2倍の時間がかかります(どちらも速度はほぼ同じです)。listtuple

編集:

Svenの答えは完全に正しいですが、完全を期すために、実際のフィルターで実行される更新されたテストは次のとおりです。

import time

def testFilter ( n, test, rangeSize ):
    for method in ( set, list, tuple ):
        t = time.time()
        for i in range( n ):
            method( filter( test, range( rangeSize ) ) )
        print( method.__name__, ( time.time() - t ) )

testFilter( 100000, lambda x: x % 3 == 0, 1000 )

結果は、実際には何がより理にかなってlistおり、tuple両方が最速であることを示していますが、セットは実際には遅くはないので、何を使用しても違いはありません。

set 27.868000030517578
list 27.131999969482422
tuple 27.138000011444092
4

2 に答える 2

11

filter()Python 3でイテレータを返します。このイテレータは、内部のforループの最初の実行で消費されます。その後、あなたは建設業者の速度を測定しているだけです-それがあなたがそれを少なくとも少しの時間を消費させるためにそれを頻繁に繰り返さなければならない理由です。

したがって、のコンストラクタはset()、空のイテレータを処理する上で最速のコンストラクタのようです。

于 2011-11-10T23:20:08.793 に答える
4

タイミングが非論理的な結果を示唆している場合、多くの場合、障害があるのはタイミングスイート自体です;-)

一般的なタイミングの間違いを回避するのに役立つtimeitモジュールを使用してみてください。特に、テストごとに新しいセットアップを実行し、本体とテストコードではなく、ループ本体の時間を計測する必要があります。

この場合、少なくともタイミングを比較可能にし(Python3のバージョンの*filterによって返される新しいイテレーターをすべて使用します)、信じられないほど速いタイミングを示します(method(iterator)コードのみがタイミングをとっていたため)ループ内)。

FWIW、過度に単純なループが完全に最適化されるため、 pypyのタイミングはさらに難しくなります。

[編集された質問への回答]新しいタイミングは同等です(良い改善)が、結果はセットアップ時間とループ時間の組み合わせを示しているため、重要な違いを確認するのは困難です。セットはより多くの作業を行う必要があるため(単に入力を格納するのではなく、各入力をハッシュする)、リストとタプルがセットを打ち負かすことを期待する必要があります。

于 2011-11-10T23:29:32.503 に答える