Ниже приведены грубые рекомендации и обоснованные предположения, основанные на опыте. Вы должны timeit
или профилировать ваш конкретный вариант использования, чтобы получить точные цифры, и эти цифры могут иногда не соответствовать приведенным ниже.
Понимание списка обычно немного быстрее, чем точно эквивалентный for
цикл (который фактически строит список), скорее всего потому, что ему не нужно искать список и его append
метод на каждой итерации. Однако, понимание списка все еще делает цикл уровня байт-кода:
>>> dis.dis(<the code object for `[x for x in range(10)]`>)
1 0 BUILD_LIST 0
3 LOAD_FAST 0 (.0)
>> 6 FOR_ITER 12 (to 21)
9 STORE_FAST 1 (x)
12 LOAD_FAST 1 (x)
15 LIST_APPEND 2
18 JUMP_ABSOLUTE 6
>> 21 RETURN_VALUE
Использование понимания списка вместо цикла, который не создает список, бессмысленное накопление списка бессмысленных значений и затем выбрасывание списка, часто медленнее из-за накладных расходов на создание и расширение списка. Понимание списка не волшебство, которое по своей природе быстрее чем старый добрый цикл.
Что касается функций обработки функциональных списков: хотя они написаны на C и, вероятно, превосходят эквивалентные функции, написанные на Python, они не обязательно являются самым быстрым вариантом. Некоторое ускорение ожидается, если функция также написана на C. Но в большинстве случаев с использованием lambda
(или другой функции Python) затрат на повторную настройку стековых фреймов Python и т. Д. Расходуется любая экономия. Простое выполнение той же самой работы in-line, без вызовов функций (например, понимание списка вместо map
или filter
) часто немного быстрее.
Предположим, что в игре, которую я разрабатываю, мне нужно рисовать сложные и огромные карты, используя циклы. Этот вопрос был бы определенно актуален, так как, если, например, понимание списка действительно быстрее, это был бы гораздо лучший вариант, чтобы избежать задержек (несмотря на визуальную сложность кода).
Скорее всего, если подобный код недостаточно быстр, когда он написан на хорошем неоптимизированном Python, никакая микрооптимизация на уровне Python не сделает его достаточно быстрым, и вы должны начать думать о переходе на С. Микрооптимизации часто могут значительно ускорить код Python, для этого существует низкий (в абсолютном выражении) предел. Более того, даже до того, как вы достигнете этого потолка, становится просто более экономически эффективным (ускорение на 15% против ускорения на 300% с тем же усилием), чтобы прикусить пулю и написать немного C.
Вы спрашиваете конкретно о
map()
,filter()
иreduce()
, но я предполагаю, что вы хотите знать о функциональном программировании в целом. Испытав это сам на проблеме вычисления расстояний между всеми точками в наборе точек, функциональное программирование (с использованиемstarmap
функции из встроенногоitertools
модуля) оказалось немного медленнее, чем циклы for (занимая в 1,25 раза больше времени, в факт). Вот пример кода, который я использовал:Функциональная версия быстрее процедурной?
источник
Я написал простой скрипт, который проверяет скорость, и вот что я узнал. На самом деле для цикла было самым быстрым в моем случае. Это действительно удивило меня, посмотрите ниже (вычислялась сумма квадратов).
источник
int
insquare_sum4
также делает его немного быстрее и чуть медленнее, чем цикл for.Я изменил код @ Алисы и использовал,
cProfile
чтобы показать, почему понимание списка происходит быстрее:Вот результаты:
ПО МОЕМУ МНЕНИЮ:
reduce
иmap
в целом довольно медленно. Мало того, что использование возвращаемыхsum
итераторовmap
является медленным, по сравнениюsum
со спискомfor_loop
использует append, который, конечно, в некоторой степени медленныйsum
намного быстрее, в отличие отmap
источник
Добавив поворот к ответу Alphii , фактически цикл for будет вторым лучшим и примерно в 6 раз медленнее, чем
map
Основные изменения были направлены на устранение медленных
sum
звонков, а также, возможно, ненужныхint()
в последнем случае. Помещение цикла for и map в одни и те же термины делает это фактически фактом. Помните, что лямбды являются функциональными концепциями и теоретически не должны иметь побочных эффектов, но, ну, у них могут быть побочные эффекты, такие как добавление кa
. Результаты в этом случае с Python 3.6.1, Ubuntu 14.04, Intel® Core Core ™ TM i7-4770 CPU @ 3.40 ГГцисточник
Мне удалось изменить часть кода @ alpiii и обнаружил, что понимание списка немного быстрее, чем для цикла. Это может быть вызвано тем
int()
, что это несправедливо между пониманием списка и циклом for.источник