这是一个函数阶乘,你几乎要求它:
>>> def fact(n): return reduce (lambda x,y: x*y, range(1,n+1))
...
>>> fact(5)
120
它不适用于 fact(0),但您可以担心 fact 范围之外的问题 :)
Masi 曾询问函数式风格是否比 Richie 的实现更高效。根据我的快速基准测试(令我惊讶的是!)是的,我的速度更快。但是我们可以做一些改变。
首先,我们可以按照另一条评论中的建议将lambda x,y: x*y 替换为operator.mul。 Python 的 lambda 运算符带来了不小的开销。其次,我们可以用xrange 代替range。 xrange 应该在线性空间中工作,根据需要返回数字,而 range 一次创建整个列表。 (请注意,您几乎可以肯定必须使用xrange 来处理过大的数字范围)
所以新的定义变成了:
>>> import operator
>>> def fact2(n): return reduce(operator.mul, xrange(1,n+1))
...
>>> fact2(5)
120
令我惊讶的是,这实际上导致性能下降。以下是问答基准:
>>> def fact(n): return (lambda x,y: x*y, range(1,n+1))
...
>>> t1 = Timer("fact(500)", "from __main__ import fact")
>>> print t1.timeit(number = 500)
0.00656795501709
>>> def fact2(n): return reduce(operator.mul, xrange(1,n+1))
...
>>> t2 = Timer("fact2(500)", "from __main__ import fact2")
>>> print t2.timeit(number = 500)
0.35856294632
>>> def fact3(n): return reduce(operator.mul, range(1,n+1))
...
>>> t3 = Timer("fact3(500)", "from __main__ import fact3")
>>> print t3.timeit(number = 500)
0.354646205902
>>> def fact4(n): return reduce(lambda x,y: x*y, xrange(1,n+1))
...
>>> t4 = Timer("fact4(500)", "from __main__ import fact4")
>>> print t4.timeit(number = 500)
0.479015111923
>>> def fact5(n):
... x = 1
... for i in range(1, n+1):
... x *= i
... return x
...
>>> t5 = Timer("fact5(500)", "from __main__ import fact5")
>>> print t5.timeit(number = 500)
0.388549804688
这是我的 Python 版本,以防有人想交叉检查我的结果:
Python 2.6.2 (release26-maint, Apr 19 2009, 01:56:41)
[GCC 4.3.3] on linux2