我有一个函数,我试图制作部分版本,然后在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'
如果我更改代码以使多个posistional参数并更新部分函数,那么是一个额外的好处;
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语句可以很好地处理血腥的事情。
任何人都可以向我解释这个吗?我可以找到这种类型错误的唯一答案似乎适用于有人在函数中调用某个东西作为关键字和正常参数的东西 - 据我所知,这里没有发生 - 如果这是在正常调用时,部分函数不能正常工作。解决方案'使多元化的位置论证是可行的,但我真的很想知道是什么导致了这个错误,因为显然我必须误解一些至关重要的事情。
编辑:感谢回答我问题的海报 - 我现在明白为什么会发生这种情况以及为什么重新排序论点或让它们定位解决问题,所以我将其标记为已解决。
然而,我确实想知道是否有一个整洁的'这样做的方式 - 一个类似于操作符的部分操作符,如果正确传递参数,它不会返回一个像所需函数一样的部分对象,但字面上会返回一个任意的所需函数,而不需要预定义任意函数。 EG: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
答案 0 :(得分:1)
这完全符合参数的排序。在您使用a=1, b=2
与使用两个第一个参数的reduce()
明确绕过订单的测试用例中,它确实失败了。
但是,如果你转过身来,这似乎有效:
def base_function(a=0, b=0, mult=10):
return mult * (a + b)
这似乎对我有用,至少!
以下情况很可能也会在您的情况下失败:
print(test_function2(1, 2))
这是因为它试图设置mult
两次......
答案 1 :(得分:1)
@horoy是对的。
另一种解释方式:
在幕后,对reduce
的调用会产生错误,最终会收到如下调用:
test_function2(x, y, mult=1)
其中x
和y
是reduce
函数的局部变量。
你可以尝试一下,轻松看看这不是一个有效的电话。传递的第一个参数必须对应于mult
,因为这是函数的第一个参数,但随后mult
传递另一个值,作为kw arg。
在你的测试中调用有效的部分函数时,你将a
和b
作为kwargs传递,绕过了这个问题。
结论是,当使用partial时,最好以这样的方式设计它来绑定函数的最后一个参数,而不是第一个。