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