これは、あなたがほとんど求めていた関数階乗です。
>>> 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
驚いたことに、これにより実際にパフォーマンスが低下しました。Q&D ベンチマークは次のとおりです。
>>> 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