142

如果我这样定义一个带有关键字参数的类方法:

class foo(object):
  def foodo(thing=None, thong='not underwear'):
    print thing if thing else "nothing" 
    print 'a thong is',thong

调用该方法会生成一个TypeError

myfoo = foo()
myfoo.foodo(thing="something")

...
TypeError: foodo() got multiple values for keyword argument 'thing'

这是怎么回事?

4

7 回答 7

171

问题是传递给 python 中类方法的第一个参数始终是调用该方法的类实例的副本,通常标记为self. 如果类是这样声明的:

class foo(object):
  def foodo(self, thing=None, thong='not underwear'):
    print thing if thing else "nothing" 
    print 'a thong is',thong

它的行为符合预期。

解释:

没有self作为第一个参数,当myfoo.foodo(thing="something")执行时,foodo使用 arguments 调用该方法(myfoo, thing="something")。然后将实例myfoo分配给thing(因为thing是第一个声明的参数),但 python 也尝试分配"something"thing,因此出现异常。

为了演示,请尝试使用原始代码运行它:

myfoo.foodo("something")
print
print myfoo

您将输出如下:

<__main__.foo object at 0x321c290>
a thong is something

<__main__.foo object at 0x321c290>

您可以看到“thing”已被分配了对“foo”类的实例“myfoo”的引用。文档的这一部分解释了函数参数是如何工作的。

于 2013-09-23T00:08:45.833 回答
50

感谢您的指导性帖子。我想提醒一下,如果您收到“TypeError: foodo() got multiple values for keyword argument 'thing'”,也可能是您错误地将 'self' 作为参数传递时调用该函数(可能是因为您从类声明中复制了该行 - 这是一个赶时间的常见错误)。

于 2014-07-24T20:27:57.010 回答
30

这可能很明显,但它可能对从未见过它的人有所帮助。如果您错误地按位置和显式地按名称分配参数,常规函数也会发生这种情况。

>>> def foodo(thing=None, thong='not underwear'):
...     print thing if thing else "nothing"
...     print 'a thong is',thong
...
>>> foodo('something', thing='everything')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: foodo() got multiple values for keyword argument 'thing'
于 2015-08-05T03:20:54.053 回答
7

如果您将其中一个键与位置参数相似(具有相同字符串名称)的关键字参数传递给位置参数,也会发生此错误。

>>> class Foo():
...     def bar(self, bar, **kwargs):
...             print(bar)
... 
>>> kwgs = {"bar":"Barred", "jokes":"Another key word argument"}
>>> myfoo = Foo()
>>> myfoo.bar("fire", **kwgs)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: bar() got multiple values for argument 'bar'
>>> 

“火”已被纳入“酒吧”论点。然而,在 kwargs 中还有另一个“酒吧”论点。

在将其传递给方法之前,您必须从 kwargs 中删除关键字参数。

于 2017-08-30T10:33:45.213 回答
6

只需将“staticmethod”装饰器添加到函数中即可解决问题

class foo(object):
    @staticmethod
    def foodo(thing=None, thong='not underwear'):
        print thing if thing else "nothing" 
        print 'a thong is',thong
于 2015-09-24T11:47:41.840 回答
4

我想再添加一个答案:

当您尝试在调用函数中传递位置顺序错误的位置参数以及关键字参数时,就会发生这种情况。

there is difference between parameter and argument你可以在这里详细阅读Arguments and Parameter in python

def hello(a,b=1, *args):
   print(a, b, *args)


hello(1, 2, 3, 4,a=12)

因为我们有三个参数:

a 是位置参数

b=1 是关键字和默认参数

*args 是变长参数

所以我们首先将 a 指定为位置参数,这意味着我们必须按照位置参数的位置顺序为位置参数提供值,这里的顺序很重要。但是我们在调用函数中将参数 1 传递给 a ,然后我们也为 a 提供值,将其视为关键字参数。现在 a 有两个值:

一是位置值:a=1

第二个是关键字值,即 a=12

解决方案

我们必须更改hello(1, 2, 3, 4,a=12)hello(1, 2, 3, 4,12) ,现在 a 将仅获得一个位置值,即 1,b 将获得值 2,其余值将获得 *args(可变长度参数)

附加信息

如果我们希望 *args 应该得到 2,3,4 并且 a 应该得到 1 并且 b 应该得到 12

那么我们可以这样做
def hello(a,*args,b=1): pass hello(1, 2, 3, 4,b=12)

更多的东西:

def hello(a,*c,b=1,**kwargs):
    print(b)
    print(c)
    print(a)
    print(kwargs)

hello(1,2,1,2,8,9,c=12)

输出 :

1

(2, 1, 2, 8, 9)

1

{'c': 12}
于 2016-10-10T11:56:22.463 回答
1

如果您使用 jquery ajax 到 url 反转到不包含“请求”参数的函数,这也可能在 Django 中发生

$.ajax({
  url: '{{ url_to_myfunc }}',
});


def myfunc(foo, bar):
    ...
于 2016-05-31T09:36:58.270 回答