[英]Interaction between functools.partial and functools.reduce
我有一个函数,我正在尝试创建它的部分版本,然后在 reduce 语句中应用该部分函数。
偏函数本身是有效的——因为我可以用一组参数正常调用它,它会返回正确的答案。 但是,如果在减少下应用它会中断
例如;
import functools
test=[1,2,3,4]
def base_function(mult=10,a=0,b=0):
return(mult*(a+b))
#control function, should act like partial base_function with mult=1
def test_function1(a=0,b=0):
return(a+b)
#stupid partial function that has destroyed my friday afternoon
test_function2=functools.partial(base_function,mult=1)
print(test_function2.args) #returns ()
print(test_function2.keywords) #returns {'mult':1}
print(test_function1(a=1,b=2)) #returns 3 as expected
print(test_function2(a=1,b=2)) #returns 3 as expected! horray!
#so the partial function itself works when called normally
print(functools.reduce(test_function1,test,-20)) #returns -10
print(functools.reduce(test_function2,test,-20)) #returns TypeError: base_function() got multiple values for argument 'mult'
如果我更改代码以生成 mult 一个位置参数并更新部分函数,作为额外的奖励;
def base_function(mult,a=0,b=0):
return(mult*(a+b))
def test_function1(a=0,b=0):
return(a+b)
test_function2=functools.partial(base_function,1)
print(test_function2.args)
print(test_function2.keywords)
该血腥的事情与reduce 语句完美配合。
任何人都可以向我解释这一点吗? 对于这种类型错误,我能找到的唯一答案似乎适用于有人将函数中的某个东西作为关键字和普通参数调用的情况——据我所知,这里没有发生过——如果是这种情况正常调用时,部分函数不应正常工作。 使 mult 成为位置参数的“解决方案”是可行的,但我真的更想知道是什么导致了这个错误,因为显然我一定误解了一些关键的东西。
编辑:感谢回答我问题的海报 - 我现在明白为什么会发生这种情况以及为什么重新排列参数或使它们具有位置性可以解决问题,所以我将其标记为已解决。
然而,我确实想知道是否有一种“整洁”的方法来做到这一点 - 一个像部分一样的运算符,它不只是返回一个部分对象,如果参数传递正确,它就像所需的函数一样,而是从字面上返回一个任意所需的函数,没有那个需要预定义的任意函数。 例如:
import functools
def base_function(mult=10,a=0,b=0):
return(mult*(a+b))
def test_function1(a=0,b=0):
return(a+b)
test_function2=partial_like_operator(base_function,mult=1)
print(test_function2==test_function1) #prints true
这一切都在参数的排序中。 在您通过使用a=1, b=2
与使用前两个参数的reduce()
显式绕过顺序的测试用例中,它确实失败了。
但是,如果你把它转过来,这似乎有效:
def base_function(a=0, b=0, mult=10):
return mult * (a + b)
这似乎对我有用,至少!
在您的情况下,以下很可能也会失败:
print(test_function2(1, 2))
这是因为它试图设置mult
...
@horoy 是对的。
另一种解释方式:
在幕后,调用reduce
会产生错误,最终调用如下:
test_function2(x, y, mult=1)
其中x
和y
是reduce
函数的局部变量。
您可以尝试一下,很容易亲眼看到这不是一个有效的调用。 传递的第一个参数必须对应于mult
因为这是函数的第一个参数,但随后mult
被传递了另一个值,作为 kw arg。
在您调用起作用的部分函数的测试中,您将a
和b
作为 kwargs 传递,从而绕过了这个问题。
结论是,在使用 partial 时,最好将其设计为绑定函数的最后一个参数,而不是第一个参数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.