kilobaik
kilobaik

Reputation: 77

What is the difference between these two solutions - lambda or loop - Python

I want to calculate the sum of even numbers within a domain. I have two solutions, but I'm not sure of the advantages/disadvantages of each. Which is the optimal solution?

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))

Upvotes: 7

Views: 12545

Answers (4)

Alex Martelli
Alex Martelli

Reputation: 881467

Here are the speeds of the various versions on an old-ish Mac laptop:

$ 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

Note that, while the genexp version is no doubt more cool, the listcomp is marginally faster (probably not by enough to worry about unless this code is in a tight inner loop you're striving to optimize the snot out of;-). As usual, the lambda-based version is substantially slower, as others have mentioned -- lambda is kind of a "poor relation" in Python:-(. ((Not that a defined function would perform noticeably better here, either))

Upvotes: 7

mechanical_meat
mechanical_meat

Reputation: 169264

+1 to the other great answers.

Bonus: the generator expression is faster...

$ 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.

Upvotes: 2

Amber
Amber

Reputation: 526473

The second really should be just a generator, not a list comprehension (since you don't actually need to create a list to be able to sum the output of a generator):

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

It's the now-preferred ("pythonic") way for accomplishing this task.

  • Using a list comprehension (the one including the [], your original Cal2) is disadvantageous because it actually constructs a list object to return, which has overhead.

  • Using filter (your Cal1) is equivalent to a generator (the no-[] version), but requires a bit more typing and doesn't read quite as well as just using a generator expression (the code I posted above).

Upvotes: 13

mikej
mikej

Reputation: 66263

Your second way of doing it is what is called a list comprehension. List comprehensions can be used to achieve the things you would previously use filter and map for prior to their introduction to the language. See this previous question for a discussion on list comprehensions vs map which is similar to what you are asking.

As Amber writes, the recommended Pythonic way to do it is to use a generator. With the list comprehsions your entire filtered list is built and then summed. With the generator it is summed as it goes along without ever having the full list in memory. This makes more of a difference when you are working with more than 10 items.

Upvotes: 2

Related Questions