Python减少功能

Sea*_*ney 1 python reduce lambda

我只是在学习 Python,不明白我从 reduce 函数中得到的行为。我看过很多例子,当你想乘法时,你可以使用 reduce 来执行与 sum 等效的函数:

f = [2,3,4]
reduce(lambda x,y: x*y,f)
Run Code Online (Sandbox Code Playgroud)

这给了我我期望的价值。但我需要乘以所有的倒数。我以为我可以这样做:

reduce(lambda x,y: 1/x * 1/y, f)
Run Code Online (Sandbox Code Playgroud)

但结果是 1.5 而不是一些小得多的十进制答案。我究竟做错了什么?

Sha*_*ger 5

x每次调用是最后一次通话的结果(这是只对第一个调用的直接投入一个),这样1 / x每次取前一个结果的倒数。要修复,您需要将 更改lambda为仅乘以新数字的倒数,而不是累加值。您还需要提供一个初始中性值 ( 1) 以便f正确取倒数中的第一个值(否则,它将是f[0]乘以 的倒数的纯值f[1:]):

# x is accumulated product of reciprocals to date, *DON'T* take reciprocal again
reduce(lambda x, y: x * (1 / y), f, 1)
                                  # ^ multiplicative identity is correct neutral value here
Run Code Online (Sandbox Code Playgroud)

也就是说,您可以稍微简化一些;x * (1 / y)是(粗略地,考虑到浮点精度问题)相当于x / y,因此您可以进一步简化为:

reduce(lambda x, y: x / y, f, 1)
Run Code Online (Sandbox Code Playgroud)

或使用operator模块来推动各项工作,以C层(如果只有重要的f可能是非常大的):

import operator
reduce(operator.truediv, f, 1)
Run Code Online (Sandbox Code Playgroud)

无论哪种方式,这都会得到预期的结果:

>>> (1/2) * (1/3) * (1/4)
0.041666666666666664
>>> reduce(lambda x,y: x * (1 / y), f, 1)
0.041666666666666664
>>> reduce(lambda x,y: x / y, f, 1)
0.041666666666666664
>>> reduce(operator.truediv, f, 1)
0.041666666666666664
Run Code Online (Sandbox Code Playgroud)

正如下面的评论中所指出的,计算单个倒数并将它们全部相乘int比仅计算 中所有值的乘积更慢且更容易出错(尤其是当所有输入为 时)f,然后计算该乘积的倒数一次,在最后。在 Python 3.8+ 上,使用math.prod,这很简单:

>>> 1 / math.prod(f)
0.041666666666666664
Run Code Online (Sandbox Code Playgroud)

在旧版本的 Python 上,您必须创建自己的产品计算函数,但使用reduce+很容易做到operator.mul

>>> 1 / reduce(operator.mul, f)
0.041666666666666664
Run Code Online (Sandbox Code Playgroud)

  • 为什么不把所有的数字相乘,然后在最后一步做倒数呢?应该有更好的准确性。 (3认同)