В чем разница между этими двумя решениями - лямбда или петля - Python - PullRequest
7 голосов
/ 19 июня 2010

Я хочу рассчитать сумму четных чисел в домене.У меня есть два решения, но я не уверен в преимуществах / недостатках каждого из них.Какое оптимальное решение?

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 ]

13 голосов
/ 19 июня 2010

Второе действительно должно быть просто генератором, а не пониманием списка (поскольку на самом деле вам не нужно создавать список для суммирования выходных данных генератора):

Cal2 = sum(n for n in domain if n % 2 == 0)

Это предпочтительный ("питонический") способ решения этой задачи.

  • Использование понимания списка (которое включает в себя [], ваш исходный Cal2) невыгодно, поскольку оно фактически создает возвращаемый объект списка, который имеет накладные расходы.

  • Использование filter (ваш Cal1) эквивалентно генератору (версия без []), но требует немного большего набора текста и не так хорошо читает, как просто использование генератора выражение (код, который я разместил выше).

7 голосов
/ 19 июня 2010

Ниже приведены скорости различных версий на ноутбуке 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 могла бы заметно работатьлучше и здесь))

2 голосов
/ 19 июня 2010

+ 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

Документы re timeit .

2 голосов
/ 19 июня 2010

Ваш второй способ сделать это - то, что называется пониманием списка. Постижения списков могут быть использованы для достижения того, что вы ранее использовали filter и map для их ознакомления с языком. См. этот предыдущий вопрос , где обсуждается понимание списка по сравнению с картой, аналогичное тому, что вы спрашиваете.

Как пишет Amber , рекомендуемый Pythonic способ сделать это - использовать генератор. С учетом списка весь ваш отфильтрованный список строится и затем суммируется. С генератором он суммируется, как и всегда, без полного списка в памяти. Это имеет большее значение, когда вы работаете с более чем 10 элементами.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...