对Python的reduce函数感到困惑

2 投票
4 回答
730 浏览
提问于 2025-04-18 00:41

我在尝试理解Python的reduce这个内置方法是怎么工作的,所以我试了一些简单的例子。但这里有一个例子我不太明白,如果有人能给我一些提示,我会非常感激。

我有一个数组,里面有几个质数,像这样:

>>> arr
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199]

然后我尝试像这样使用reduce函数:

>>> reduce(lambda x, y: is_prime(x) and is_prime(y), arr)
False

我不太明白为什么这里的答案是False而不是True,因为我只是把is_prime的所有结果进行与运算,而数组中的所有数字都是质数,这样is_prime应该对每个数字都返回True。

我还检查了数组中的每个数字实际上都对我的is_prime()返回True:

>>> for n in arr:
...     if not is_prime(n):
...         print n
...
>>>

我一定是漏掉了什么,有人能帮忙吗?谢谢。

4 个回答

0

传给reduce()的这个有两个参数的函数,应该返回一个和输入类型相同的值,也就是说,它是把两个值“缩减”成一个值;reduce()会反复应用这个函数,把整个输入的可迭代对象(比如列表)缩减成一个单一的值。

经典的例子是:用 lambda x,y:x+y 来计算输入的总和。

如果你想要的结果是判断列表中的每个数字是否都是质数,可以使用内置的all()函数:

they_are_all_primes=all((is_prime(x) for x in [2,3,5])) 
0

在这个lambda表达式中,第一个参数(x)是累积值,第二个参数(y)是迭代值。试试这个:

reduce(lambda x, y: x and is_prime(y), arr, True)

所以x会被替换为从True开始的累积值(初始的累积值),这样True和is_prime(2)的结果是True,所以True会传递到下一次迭代中……

接下来我们来实验一下,检查所有的数字是否都是奇数:

>>> arr = [3, 5, 7, 11, 15]
>>> reduce(lambda x, y: x and y%2!=0, arr, True)
True

现在我将定义一个函数,用来打印中间的累积值:

>>> def xxx(y):
...    print y
...    return y
...
>>> reduce(lambda x, y: xxx(x) and y%2!=0, arr, True)
True
True
True
True
True
True
>>> arr = [3, 5, 7, 12, 15]
>>> reduce(lambda x, y: xxx(x) and y%2!=0, arr, True)
True
True
True
True
False
False
>>>

这样命名变量会更清晰:

reduce(lambda accumulated, number: accumulated and is_prime(number), arr, True)
1
is_prime(x) and is_prime(y)

这段代码的结果会是一个布尔值,也就是说它的结果要么是“真”(True),要么是“假”(False)。在下一次循环中,这个结果会作为参数传给lambda函数的 x

所以,如果有任何一次调用 is_prime 返回 False,那么整个结果就会变成 False。因为:

第一次循环:

(Default Value & First Value)

从第二次循环开始:

(Previous Result & Current Value)

由于这是一个“与”(and)操作的系列,如果其中任何一个结果是 False,那么整个表达式的结果就会被评估为 False

4

想想你正在一个一个地处理这些值:

>>> reduce(lambda x,y: isprime(x) and isprime(y), [2])
2

只有一个元素,所以 reduce 直接给我们第一个。

>>> reduce(lambda x,y: isprime(x) and isprime(y), [2, 3])
True

这很合理:两个都是质数。

>>> reduce(lambda x,y: isprime(x) and isprime(y), [2, 3, 5])
False

这个看起来有点奇怪,但其实是因为你实际上在调用

isprime(True) and isprime(5)

因为 True 是最后一个值,而 Trueint 值是 1:

>>> int(True)
1

reduceall 是不一样的。

撰写回答