【问题标题】:Understanding TypeError: got multiple values for keyword argument理解 TypeError:为关键字参数获取多个值
【发布时间】:2017-07-14 04:22:48
【问题描述】:

我尝试了不同的方法来调用带有 *args 的方法。下面是我的代码片段。

def total(name, *args):
    if args:
        print("%s has total money of Rs %d/- " %(name, sum(args)))
    else:
        print("%s's piggy bank  has no money" %name)

现在有两种方法可以调用这个方法。一种是在 *() 中传递额外的参数,或者直接用逗号分隔。我故意以 param=value 的形式传递 'name' 的值,这样它就会引发错误。以下是我尝试的两种方法:-

1 - 传递额外的参数逗号分隔:-

>>> total(name="Adi", 1, 2, 10 )
  File "<stdin>", line 1
SyntaxError: non-keyword arg after keyword arg

2 - 使用 *() 传递额外的参数:-

>>> total(name="Adi", *(1, 2, 10) )
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: total() got multiple values for keyword argument 'name'

第一个错误消息非常清楚,它传达了确切的错误。但是,我无法理解第二次调用的错误消息。

Python 如何评估第二次调用它为参数“name”获取多个值?我想到的可能方式是内部 Python 将是翻译

total(name="Adi", *(1, 2, 10))

如下:-

总计(*(1, 2, 10), name="Adi" )

在上面的翻译中,根据位置,'name' 得到值 *(1,2,10),然后又得到“Adi”。因此可以理解多值错误。

但是,我不确定,python 内部是否会改变位置?对此的任何见解都会有所帮助。

【问题讨论】:

  • total(name-"Adi", 1, 2, 10 ) 无效,因为 - 符号。您确定要向我们展示真实代码吗?
  • 我的错。错过了。

标签: python python-2.7


【解决方案1】:

我使用inspect 模块检查了该方法。检查模块中的 getcallargs() 方法为您提供传递的值到方法参数的映射。

def total(name, *args):
    if args:
        print("%s has total money of Rs %d/- " %(name, sum(args)))
    else:
        print("%s's piggy bank  has no money" %name)

#total(name="Adi", *(1, 2, 10) )
# equivalent call using inspect module
import inspect
print inspect.getcallargs(total, 'Adi', *(1, 2, 10) )

因此,当调用方法时,所有传递的参数都采用以下两种形式之一

*positional :- 所有位置参数(不带关键字)和在 *() 中传递的参数或额外的非关键字参数的元组

**named :- 以 param=value 形式传递的所有参数的字典,以及额外的关键字参数

所以在我的电话total(name="Adi", *(1, 2, 10) ) 中,'positional' 元组的值是 (1,2,10),'named' 字典的值是 {'name':'Adi'}

然后它将值分配给参数。在赋值期间,强制参数首先被赋值。 Python 检查强制参数列表(此处为 ['name'])并按顺序从 'positional' 元组中分配值。元组中未分配的任何值都被假定为额外参数(非关键字参数)。

因此参数'name' 获得分配给它的值1。其余的值(即 2 和 10)被假定为额外参数。

接下来,它会检查方法的签名中是否包含非关键字参数。如果是这样,那么来自'positional' 元组的剩余值被分配给相同的值。所以这里 'args' 被分配给剩余的值,即 (2,10) 的元组。

但是,如果方法签名中没有非关键字参数,并且'positional' tuple 有一些值仍未分配,那么 python 会抛出错误“方法只接受 X 参数 Y 给定”Y 大于 X。

一旦分配了来自'positional' 的所有值,就会分配来自'named' 字典的值。在这种情况下,解释器首先检查字典中是否存在任何强制参数,即任何强制参数的值是否在方法调用中以&lt;param=value&gt; 的形式传递?如果是,那么接下来它会检查在分配来自'positional' 元组的值期间是否已为这些强制参数分配了任何值?

如果是这样,那么它会为同一个参数找到两个值(一个来自'positional',另一个来自'named'),因此抛出"got multiple values for keyword argument" 错误。否则,它将值分配给来自'named' 字典的参数。

以这种方式,在上述情况下,参数'name' 是强制参数,并且存在于'named' 字典中,因为我在方法调用中传递了name="Adi"。在分配位置值(来自'positional' 元组的值)期间,变量'name' 获得了分配给它的值1。从命名参数字典(来自'named' 字典的值)中,它具有值'Adi',这使得2 个值被分配给变量'name'。因此我们得到了错误:-

total() 为关键字参数 'name' 获得了多个值

因此,在传递非关键字额外参数时,只需传递强制参数的值,这将使其具有位置性。但是,不是&lt;param=val&gt; 的形式,这将使它命名并为参数获取两个值,因此将引发错误。因此不建议以&lt;param = value &gt;的形式传递强制参数。

所以调用方法的正确方法是:-

总计('Adi', *(1,2,10))

总计('Adi', 1, 2, 10)

【讨论】:

    猜你喜欢
    • 2016-04-25
    • 1970-01-01
    • 1970-01-01
    • 2018-04-22
    • 2017-06-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-27
    相关资源
    最近更新 更多