这是您几乎要求的功能阶乘:
>>> def fact(n): return reduce (lambda x,y: x*y, range(1,n+1))
...
>>> fact(5)
120
它不适用于事实(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