了解TypeError:为关键字参数

时间:2017-02-23 15:31:33

标签: python python-2.7

我正在尝试使用* 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 - 将额外的params逗号分开: -

>>> 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将翻译

  

总计(姓名=“Adi”,*(1,2,10))

如下: -

  

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

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

但是,我不确定,内部的python是否会改变这些立场?任何有关这方面的见解都会有所帮助。

1 个答案:

答案 0 :(得分:1)

我使用inspect模块检查了方法。来自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) )

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

  

*位置: - 所有位置参数的元组(没有关键字)和在*()内传递的参数或额外的非密钥参数

     

**命名: - 以param = value形式传递的所有参数的字典,以及额外的keyworded参数

因此,在我的电话total(name="Adi", *(1, 2, 10) )中,'positional'元组有值(1,2,10),'named'字典有价值{&#39; name&#39;:&#39 ;阿迪&#39;}

然后它将值赋值给参数。在分配期间,首先分配强制参数。 Python检查强制参数列表(这里[&#39; name&#39;])并按顺序分配'positional'元组的值。来自未分配的元组的任何值都被假定为额外参数(非密钥参数)。

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

接下来,它检查方法是否在其签名中包含非keyworded参数。如果是,则将'positional'元组的剩余值分配给它们。所以这里'args'被赋予剩余的值,即(2,10)的元组。

但是,如果方法签名中没有非关键字参数,并且'positional'元组仍有一些值未分配,那么python会抛出错误&#34;方法需要正确的X参数Y给出&#34 ; Y大于X。

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

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

以这种方式,在上面的例子中,参数'name'是强制参数,并且在'named'字典中出现,因为我在方法调用中已经通过了name="Adi"。在分配位置值(来自'positional'元组的值)期间,变量'name'已获得分配给它的值1。从命名参数的字典(来自'named'字典的值)中,它具有值&#39; Adi&#39;,它将2个值分配给变量'name'。因此我们得到错误: -

  

total()获得了关键字参数&#39; name&#39;

的多个值

因此,在传递非keyworded额外参数时,需要传递强制参数的值,这将使其成为位置。但是,不是<param=val>的形式,它将使它命名并将获得参数的两个值,因此将抛出错误。因此,不建议以<param = value >的形式传递强制参数。

因此调用该方法的正确方法是: -

  

总计(&#39; Adi&#39;,*(1,2,10))

  

总计(&#39; Adi&#39;,1,2,10)