类方法生成“TypeError:…有多个值的关键字参数…”

如果我使用关键字参数定义一个类方法:

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' 

这是怎么回事?

问题是在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方法(myfoo, thing="something") 。 实例myfoo然后分配给thing (因为thing是第一个声明的参数),但是python也试图给"something"分配"something" ,因此exception。

为了演示,试着用原来的代码来运行它:

 myfoo.foodo("something") print print myfoo 

你会输出像:

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

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

感谢您的指导性的职位。 我只是想留意一下,如果你得到“TypeError:foodo()有多个关键字参数”thing“的值,那么也可能是你错误地将”self“作为parameter passing调用函数(可能是因为你从类声明中复制了这行 – 这是一个急于求成的常见错误)。

这可能是显而易见的,但它可能有助于以前从未见过的人。 如果您错误地按位置和名称明确分配参数,这也会发生在常规function上。

 >>> 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' 

只需添加“staticmethod”装饰器function和问题是固定的

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

我想添加一个答案:

在调用函数中尝试使用错误的位置顺序与关键字参数一起传递位置参数时,会发生这种情况。

there is difference between parameter and argument你可以在这里详细阅读关于这里参数和参数在Python中

 def hello(a,b=1, *args): print(a, b, *args) hello(1, 2, 3, 4,a=12) 

因为我们有三个参数:

a是位置参数

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

* args是可变长度参数

所以我们首先分配一个作为位置参数,意味着我们必须在其位置顺序中为位置参数提供值,这里顺序很重要。 但是我们在调用函数的地方传递参数1,然后我们也提供了一个值,作为关键字参数。 现在有两个值:

一个是位置值:a = 1

第二是keyworded值是a = 12

我们必须改变hello(1, 2, 3, 4,a=12)hello(1, 2, 3, 4,12)所以现在a将只有一个位置值是1,b将得到值2,其余的值将得到*参数(可变长度参数)

附加信息

如果我们想要* 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} 

如果您将关键字parameter passing给某个位置参数(该关键字参数的某个键相似(具有相同的string名称)),也会发生此错误。

 >>> 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中移除关键字参数。

此外,这可能发生在Django,如果您使用jQuery的Ajax到URL,反转到一个函数,不包含“请求”参数

 $.ajax({ url: '{{ url_to_myfunc }}', }); def myfunc(foo, bar): ...