"Collapsing" a list into a list of changes

Steven Bethard steven.bethard at gmail.com
Mon Feb 7 14:41:59 EST 2005


John Lenton wrote:
> For example, the fastest way
> to get the factorial of a (small enough) number in pure python is
> 
>   factorial = lambda n: reduce(operator.mul, range(1, n+1))

Gah!  I'll never understand why people use lambda, which is intended to 
create _anonymous_ functions, to create named functions!  This code is 
basically equivalent to:

     def factorial(n):
         return reduce(operator.mul, range(1, n+1))

except that factorial.__name__ is now the meaningful 'factorial', 
instead of '<lambda>'.  See "Inappropriate use of Lambda" in
     http://www.python.org/moin/DubiousPython


My personal beef with the inappropriate use of lambda aside, and 
ignoring the fact that the reduce solution as written fails for 
factorial(0), some timings are in order.  Given fact.py:

----------------------------------------------------------------------
import operator

def f1(n):
     result = 1
     for x in xrange(1, n+1):
         result *= x
     return result

def f2(n):
     return reduce(operator.mul, range(1, n+1))

def f3(n):
     return reduce(operator.mul, xrange(1, n+1))
----------------------------------------------------------------------

I get the following timeit results (with Python 2.4):

$ python -m timeit -s "import fact" "[fact.f1(x) for x in xrange(1, 100)]"
100 loops, best of 3: 2.53 msec per loop

$ python -m timeit -s "import fact" "[fact.f2(x) for x in xrange(1, 100)]"
100 loops, best of 3: 2.46 msec per loop

$ python -m timeit -s "import fact" "[fact.f3(x) for x in xrange(1, 100)]"
100 loops, best of 3: 2.17 msec per loop

So it does look like reduce is actually faster in this case, especially 
if you use xrange instead of range.

Thanks for the example!

Steve



More information about the Python-list mailing list