В чем разница между этими двумя решениями - лямбда или петля - 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

Docs re timeit.

Другие вопросы по тегам