Вот функциональный факториал, который вы почти просили:
>>> def fact(n): return reduce (lambda x,y: x*y, range(1,n+1))
...
>>> fact(5)
120
Фактически это не работает (0), но вы можете беспокоиться об этом за пределами fact
:)
Маси спросил, является ли функциональный стиль более эффективным, чем реализация Ричи. Согласно моему быстрому тесту (и, к моему удивлению!), Да, мой быстрее. Но есть пара вещей, которые мы можем сделать, чтобы измениться.
Во-первых, мы можем заменить 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