Почему создание набора из фильтра намного быстрее, чем создание списка или кортежа?

Я использую filter для объекта interable и хочу сохранить результат в последовательности (мне нужна последовательность, чтобы я можно использовать на нем random.choice ). Я заметил, что создание набора из объекта filter намного быстрее, чем создание списка или кортежа . Это почему? Сначала я подумал, что тип фильтра является подтипом набора, что объясняет это, но функция 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 занимает примерно вдвое больше времени, чем list и tuple (оба почти идентичны по скорости).

править:

Ответ Свена полностью верен, но для полноты картины обновленный тест, который будет запускаться на реальном фильтре:

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 и кортеж оба являются самыми быстрыми, хотя набор на самом деле не медленнее, поэтому не имеет значения, что использовать:

set 27.868000030517578
list 27.131999969482422
tuple 27.138000011444092
5
задан poke 10 November 2011 в 23:29
поделиться