Python缩减函数

Python缩减函数,python,lambda,reduce,Python,Lambda,Reduce,我只是在学习Python,不理解reduce函数的行为。我看到过很多例子,当您想要乘法时,可以使用reduce执行一个等价的函数求和: f = [2,3,4] reduce(lambda x,y: x*y,f) 这给了我期望的价值。但我需要乘以所有的倒数。我想我可以做到这一点: reduce(lambda x,y: 1/x * 1/y, f) 但结果是1.5,而不是一些小得多的小数点答案。我做错了什么?每次调用的x都是最后一次调用的结果(它只是第一次调用的直接输入之一),因此每次执行1/x都

我只是在学习Python,不理解reduce函数的行为。我看到过很多例子,当您想要乘法时,可以使用reduce执行一个等价的函数求和:

f = [2,3,4]
reduce(lambda x,y: x*y,f)
这给了我期望的价值。但我需要乘以所有的倒数。我想我可以做到这一点:

reduce(lambda x,y: 1/x * 1/y, f)

但结果是1.5,而不是一些小得多的小数点答案。我做错了什么?

每次调用的
x
都是最后一次调用的结果(它只是第一次调用的直接输入之一),因此每次执行
1/x
都需要上一次结果的倒数。要修复此问题,您需要将
lambda
更改为仅与新数字的倒数相乘,而不是与累积值相乘。您还需要提供一个初始中性值(
1
),以便正确地获取
f
中的第一个值的倒数(否则,它将是
f[0]
的普通值乘以
f[1:][/code>的倒数):

也就是说,你可以简化一点
x*(1/y)
大致相当于
x/y
,因此您可以进一步简化为:

reduce(lambda x, y: x / y, f, 1)
或者使用将所有工作推送到C层(仅当
f
可能非常大时才重要):

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

>>> (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
如下面的评论所述,计算单个倒数并将它们全部相乘比只计算
f
中所有值的乘积,然后在最后计算该乘积的倒数一次要慢且更容易出错(尤其是当所有输入都是
int
)。在Python 3.8+上,使用,这非常简单:

>>> 1 / math.prod(f)
0.041666666666666664
在较旧版本的Python上,您必须创建自己的产品计算功能,但使用
reduce
+:


每次调用的
x
都是最后一次调用的结果(它只是第一次调用时的直接输入之一),因此每次执行
1/x
都需要上一次结果的倒数。要修复此问题,您需要将
lambda
更改为仅与新数字的倒数相乘,而不是与累积值相乘。您还需要提供一个初始中性值(
1
),以便正确地获取
f
中的第一个值的倒数(否则,它将是
f[0]
的普通值乘以
f[1:][/code>的倒数):

也就是说,你可以简化一点
x*(1/y)
大致相当于
x/y
,因此您可以进一步简化为:

reduce(lambda x, y: x / y, f, 1)
或者使用将所有工作推送到C层(仅当
f
可能非常大时才重要):

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

>>> (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
如下面的评论所述,计算单个倒数并将它们全部相乘比只计算
f
中所有值的乘积,然后在最后计算该乘积的倒数一次要慢且更容易出错(尤其是当所有输入都是
int
)。在Python 3.8+上,使用,这非常简单:

>>> 1 / math.prod(f)
0.041666666666666664
在较旧版本的Python上,您必须创建自己的产品计算功能,但使用
reduce
+:


你有没有试过在计算中使用偏执:
reduce(lambda x,y:(1/x)*(1/y),f)
?@LukasBach:在这种情况下,括号(大部分)是不相关的(主要是因为操作顺序稍微改变了浮点数学的结果)。即使没有括号,它也会变成逻辑上等价的
((1/x)*1)/y
。问题在于
x
的含义。“取倒数”部分更适合
map
,而不是将其折叠成
reduce
reduce(lambda x,y:x*y,map(lambda x:1/x,f))
。(当然,在Python中使用
reduce
map
lambda
并不像在函数语言中那样受到鼓励,将所有的倒数相乘就相当于将所有的数字相乘,并在最后取一次倒数,这会更容易。)你试过在计算中使用偏执吗:
reduce(lambda x,y:(1/x)*(1/y),f)
?@LukasBach:在这种情况下,括号(大部分)是不相关的(主要是因为操作顺序稍微改变了浮点数学的结果)。即使没有括号,它也会变成
((1/x)*1)/y
在逻辑上是等价的。问题在于
x
的含义。对于
map
“取倒数”部分更适合,而不是将其折叠到
reduce
reduce(lambda x,y:x*y,map(lambda x:1/x,f))
。(当然,在Python中使用
reduce
map
lambda
并不像在函数语言中那样受到鼓励,将所有的倒数相乘就相当于将所有的数字相乘,并在最后取一次倒数,这会更容易。)为什么不把所有的数字相乘并做倒数作为最后一步呢?应该有更好的精度。正切:如果
f
很大,你很可能会受到浮点不精确的影响。避免这种情况的一个技巧是将操作数转换为
分数。分数
;如果你所有的操作数都是整数(无损)“
分数”
形式太复杂,因此您可以在不损失精度的情况下获得分数结果,或者在最后只转换为
浮点值,将精度损失限制为单个操作。
reduce(truediv,map(分数,f),1)
生成
分数(1,24)
,和