В чем разница между этими двумя решениями - лямбда или петля - Python
Я хочу рассчитать сумму четных чисел в домене. У меня есть два решения, но я не уверен в преимуществах / недостатках каждого из них. Какое решение является оптимальным?
import sys
domain = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Cal1 = sum(filter(lambda n : n % 2 == 0, domain))
Cal2 = sum([n for n in domain if n % 2 == 0])
sys.stdout.write("Cal1 = {0}\n".format(Cal1))
sys.stdout.write("Cal2 = {0}\n".format(Cal2))
4 ответа
Второе действительно должно быть просто генератором, а не пониманием списка (поскольку на самом деле вам не нужно создавать список, чтобы иметь возможность суммировать выходные данные генератора):
Cal2 = sum(n for n in domain if n % 2 == 0)
Это предпочтительный ("питонический") способ решения этой задачи.
Использование понимания списка (включая
[]
твой оригиналCal2
) невыгодно, поскольку фактически создает объект списка для возврата, который имеет накладные расходы.С помощью
filter
(вашCal1
) эквивалентно генератору (нет[]
версия), но требует немного большего набора текста и не читает так же хорошо, как просто использование выражения генератора (код, который я разместил выше).
Вот скорости различных версий на старомодном ноутбуке Mac:
$ py26 -mtimeit -s'domain = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]' 'sum(filter(lambda n : n % 2 == 0, domain))'
100000 loops, best of 3: 4.41 usec per loop
$ py26 -mtimeit -s'domain = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]' 'sum([n for n in domain if n % 2 == 0])'
100000 loops, best of 3: 2.69 usec per loop
$ py26 -mtimeit -s'domain = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]' 'sum(n for n in domain if n % 2 == 0)'
100000 loops, best of 3: 2.86 usec per loop
Обратите внимание, что, хотя версия genexp, без сомнения, более крутая, listcomp немного быстрее (вероятно, этого недостаточно, чтобы беспокоиться, если этот код не находится в тесном внутреннем цикле, из которого вы пытаетесь оптимизировать сопли;-). Как обычно, lambda
версия существенно медленнее, как уже упоминали другие lambda
это своего рода "плохое отношение" в Python:-(. ((Не то чтобы def
Функция ined здесь тоже будет работать заметно лучше))
Ваш второй способ сделать это - то, что называют пониманием списка. Постижения списка могут быть использованы для достижения того, что вы ранее использовали filter
а также map
за до их введения в язык. См. Этот предыдущий вопрос для обсуждения списков в сравнении с картой, которая похожа на то, что вы спрашиваете.
Как пишет Amber, рекомендуемый Pythonic способ сделать это - использовать генератор. С учетом списков весь ваш отфильтрованный список строится и затем суммируется. С генератором он суммируется, как и всегда, без полного списка в памяти. Это имеет большее значение, когда вы работаете с более чем 10 предметами.
+1 к другим отличным ответам.
Бонус: генератор выражения быстрее...
$ python -m timeit -s 'L = xrange(10)' 'sum(filter(lambda n: n % 2 == 0, L))'
100000 loops, best of 3: 3.59 usec per loop
$ python -m timeit -s 'L = xrange(10)' 'sum(n for n in L if n % 2 == 0)'
100000 loops, best of 3: 2.82 usec per loop