类方法生成“ TypeError:…为关键字参数获得了多个值……”

问题:类方法生成“ 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'

这是怎么回事?

If I define a class method with a keyword argument thus:

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

calling the method generates a TypeError:

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

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

What’s going on?


回答 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”的引用。文档的此部分说明了函数参数的工作原理。

The problem is that the first argument passed to class methods in python is always a copy of the class instance on which the method is called, typically labelled self. If the class is declared thus:

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

it behaves as expected.

Explanation:

Without self as the first parameter, when myfoo.foodo(thing="something") is executed, the foodo method is called with arguments (myfoo, thing="something"). The instance myfoo is then assigned to thing (since thing is the first declared parameter), but python also attempts to assign "something" to thing, hence the Exception.

To demonstrate, try running this with the original code:

myfoo.foodo("something")
print
print myfoo

You’ll output like:

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

<__main__.foo object at 0x321c290>

You can see that ‘thing’ has been assigned a reference to the instance ‘myfoo’ of the class ‘foo’. This section of the docs explains how function arguments work a bit more.


回答 1

感谢您的指导性帖子。我只想说明一下,如果您收到“ TypeError:foodo()为关键字参数’thing’获得多个值”,则可能是您错误地将“ self”作为参数传递的调用该函数(可能是因为您从类声明中复制了该行-急时这是一个常见错误)。

Thanks for the instructive posts. I’d just like to keep a note that if you’re getting “TypeError: foodo() got multiple values for keyword argument ‘thing'”, it may also be that you’re mistakenly passing the ‘self’ as a parameter when calling the function (probably because you copied the line from the class declaration – it’s a common error when one’s in a hurry).


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

This might be obvious, but it might help someone who has never seen it before. This also happens for regular functions if you mistakenly assign a parameter by position and explicitly by name.

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

just add ‘staticmethod’ decorator to function and problem is fixed

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}

I want to add one more answer :

It happens when you try to pass positional parameter with wrong position order along with keyword argument in calling function.

there is difference between parameter and argument you can read in detail about here Arguments and Parameter in python

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


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

since we have three parameters :

a is positional parameter

b=1 is keyword and default parameter

*args is variable length parameter

so we first assign a as positional parameter , means we have to provide value to positional argument in its position order, here order matter. but we are passing argument 1 at the place of a in calling function and then we are also providing value to a , treating as keyword argument. now a have two values :

one is positional value: a=1

second is keyworded value which is a=12

Solution

We have to change hello(1, 2, 3, 4,a=12) to hello(1, 2, 3, 4,12) so now a will get only one positional value which is 1 and b will get value 2 and rest of values will get *args (variable length parameter)

additional information

if we want that *args should get 2,3,4 and a should get 1 and b should get 12

then we can do like this
def hello(a,*args,b=1): pass hello(1, 2, 3, 4,b=12)

Something more :

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

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

output :

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中删除,然后再将其传递给方法。

This error can also happen if you pass a key word argument for which one of the keys is similar (has same string name) to a positional argument.

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

“fire” has been accepted into the ‘bar’ argument. And yet there is another ‘bar’ argument present in kwargs.

You would have to remove the keyword argument from the kwargs before passing it to the method.


回答 6

如果您使用jquery ajax的URL反向到不包含’request’参数的函数,则这也可能在Django中发生

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


def myfunc(foo, bar):
    ...

Also this can happen in Django if you are using jquery ajax to url that reverses to a function that doesn’t contain ‘request’ parameter

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


def myfunc(foo, bar):
    ...