我正在使用functools模块中的partial方法来映射一系列值的函数:
def basic_rule(p,b,vx=1,**kwargs):
return (p / b) if vx != 0 else 0
def rule5(func,**kwargs):
vals = map(functools.partial(func,**kwargs), range(1,kwargs['b']+1))
return [x for i,x in enumerate(vals[:-1]) if x >= vals[i+1]] == []
rule5(basic_rule,p=100,b=10000)
以下是第5行的错误:
----> return map(functools.partial(func,**kwargs), range(1,kwargs['b']+1))
TypeError: basic_rule() got multiple values for keyword argument 'p'
看起来functools.partial试图将范围分配给参数p,即使我已经为其分配了一个值。我试图将范围分配给vx的值。知道如何才能实现这一目标吗?
编辑:为代码添加了一些额外的上下文。基本上我要测试5要做的是确保给定的函数的结果随着vt的增加而增加,因此`func(vt = 1)< func(vt = 2)...< FUNC(VT = N)。
答案 0 :(得分:0)
functools.partial生成一个partial,它将参数receiveid存储在2个属性中:
arguments
存储位置参数keywords
存储所有基于关键字的参数因此,partial可以完全按照预期调用原始函数。换句话说,当你用一个参数(比如说1)调用结果部分时,它将与:
相同original_func(1, **kwargs)
由于你的kwargs
包含第一个参数 - 并且你将“1”作为位置参数传递 - 你会收到错误。
我不确定它是否会在这种特殊情况下起作用,但是一个解决方案可以使用inspect.getargspec从kwargs
中提取可以作为位置参数传递的参数。在这种情况下,rule5
函数类似于:
def rule5(func, **kwargs):
# let's save 'b' argument because we'll need it in the range call
b = kwargs['b']
original_args = inspect.getargspec(func).args
# extract from kwargs all arguments that can be passed as positional
new_args = [kwargs.pop(key) for key in original_args if key in kwargs]
# construct the partial passing as much positional arguments as possible
fn = functools.partial(func, *new_args, **kwargs)
# now map will pass the range result as the next positional argument
vals = map(fn, range(1, b+1))
return [x for i,x in enumerate(vals[:-1]) if x >= vals[i+1]] == []