reduce函数是如何工作的?
根据我的理解,reduce函数会接收一个列表l
和一个函数f
。然后,它会先把这个函数f
应用到列表的前两个元素上,接着再把函数f
和下一个列表元素以及之前的结果一起反复调用。
所以,我定义了以下的函数:
下面这个函数用来计算阶乘。
def fact(n):
if n == 0 or n == 1:
return 1
return fact(n-1) * n
def reduce_func(x,y):
return fact(x) * fact(y)
lst = [1, 3, 1]
print reduce(reduce_func, lst)
现在,这个计算应该给我((1! * 3!) * 1!) = 6
吧?可是,它却给了我720
。为什么是720
呢?看起来它还计算了6
的阶乘。但我需要弄明白这是为什么。
有没有人能解释一下为什么会这样,还有解决办法?
我其实是想计算列表中所有元素的阶乘的乘积。我的备选方案是用循环来计算。但我更想用reduce。
9 个回答
33
理解 reduce() 最简单的方法就是看看它在纯 Python 中的对应代码:
def myreduce(func, iterable, start=None):
it = iter(iterable)
if start is None:
try:
start = next(it)
except StopIteration:
raise TypeError('reduce() of empty sequence with no initial value')
accum_value = start
for x in it:
accum_value = func(accum_value, x)
return accum_value
你会发现,只有把阶乘函数应用到最右边的参数上,才是有意义的:
def fact(n):
if n == 0 or n == 1:
return 1
return fact(n-1) * n
def reduce_func(x,y):
return x * fact(y)
经过这个小修改,代码就能像你预期的那样输出 6 了 :-)
>>> lst = [1, 3, 1]
>>> myreduce(reduce_func, lst)
6
1
好的,明白了:
我需要先把数字和它们的阶乘对应起来,然后再用乘法操作符来调用reduce函数。
所以,这样做是可以的:
lst_fact = map(fact, lst)
reduce(operator.mul, lst_fact)