问题:类方法生成“ 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'
这是怎么回事?
回答 0
问题在于,传递给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
,因此是Exception。
为了演示,请尝试使用原始代码运行它:
myfoo.foodo("something")
print
print myfoo
您将输出如下:
<__main__.foo object at 0x321c290>
a thong is something
<__main__.foo object at 0x321c290>
您可以看到“事物”已被分配对类“ foo”的实例“ myfoo”的引用。文档的此部分说明了函数参数的工作原理。
回答 1
感谢您的指导性帖子。我只想说明一下,如果您收到“ TypeError:foodo()为关键字参数’thing’获得多个值”,则可能是您错误地将“ self”作为参数传递的调用该函数(可能是因为您从类声明中复制了该行-急时这是一个常见错误)。
回答 2
这可能很明显,但可能会对从未见过的人有所帮助。如果您错误地通过位置和名称显式地分配了参数,则对于常规函数也会发生这种情况。
>>> 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'
回答 3
只需向功能添加“ staticmethod”装饰器即可解决问题
class foo(object):
@staticmethod
def foodo(thing=None, thong='not underwear'):
print thing if thing else "nothing"
print 'a thong is',thong
回答 4
我想再添加一个答案:
当您尝试在调用函数中尝试传递位置顺序错误的位置参数以及关键字参数时,就会发生这种情况。
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是可变长度参数
因此我们首先将a作为位置参数赋值,这意味着我们必须按位置顺序向位置参数提供值,这里顺序很重要。但是我们将参数1传递给in调用函数中的位置,然后还将值提供给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}
回答 5
如果您传递的关键字自变量的键之一与位置自变量相似(具有相同的字符串名称),则也会发生此错误。
>>> 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中删除,然后再将其传递给方法。
回答 6
如果您使用jquery ajax的URL反向到不包含’request’参数的函数,则这也可能在Django中发生
$.ajax({
url: '{{ url_to_myfunc }}',
});
def myfunc(foo, bar):
...