【问题标题】:functools.partial: TypeError: got multiple values for keyword argumentfunctools.partial:TypeError:为关键字参数获取多个值
【发布时间】:2016-11-05 14:20:38
【问题描述】:

我正在使用 functools 模块中的部分方法将函数映射到一系列值:

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)

【问题讨论】:

  • basic_rule中**kwargs的作用是什么?
  • 你为什么使用functools.partial()而不是lambda?
  • 更改为 kwargs["p"] / kwargs["b"] if vx != 0 else 0 并将函数签名更改为 basic_rule(vx=1, **kwargs): 可以避免错误,但不确定您的最终目标是什么
  • @PadraicCunningham,我对每个函数(类似于 rule5)有多个测试,它们将参数传递到内部函数并测试输出。这些函数并不都有相同的关键字参数,所以我使用 **kwargs 来允许我传递函数所需的任何参数。
  • @MoeChughtai,是的,我认为可能会有,如果你添加你想要的作为输出,为什么你可能会更好地为你的问题找到一个好的解决方案。

标签: python dictionary functools


【解决方案1】:

functools.partial 生成一个将参数receiveids 存储在2 个属性中的部分:

  • arguments 存储位置参数
  • keywords 存储所有基于关键字的参数

因此,partial 可以完全按照预期调用原始函数。换句话说,当您使用一个参数(比如说 1)调用生成的部分时,它将与以下内容相同:

original_func(1, **kwargs)

由于您的 kwargs 包含第一个参数 - 并且您将“1”作为位置参数传递 - 您会收到错误。

我不确定它是否适用于这种特殊情况,但一种解决方案是使用inspect.getargspeckwargs 中提取可以作为位置参数传递的参数。在这种情况下,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]] == []

【讨论】:

    猜你喜欢
    • 2014-03-10
    • 1970-01-01
    • 2017-07-14
    • 2010-12-28
    • 2013-08-04
    • 2016-06-24
    • 2015-05-18
    • 1970-01-01
    • 2013-03-09
    相关资源
    最近更新 更多