Python 类方法生成“TypeError: ...得到了多个关键字参数值...”

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18950054/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 12:22:51  来源:igfitidea点击:

class method generates "TypeError: ... got multiple values for keyword argument ..."

pythonclasspython-2.7methods

提问by drevicko

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:

调用该方法会生成一个TypeError

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

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

What's going on?

这是怎么回事?

采纳答案by drevicko

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:

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

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 selfas the first parameter, when myfoo.foodo(thing="something")is executed, the foodomethod is called with arguments (myfoo, thing="something"). The instance myfoois then assigned to thing(since thingis the first declared parameter), but python also attempts to assign "something"to thing, hence the Exception.

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

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 sectionof the docs explains how function arguments work a bit more.

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

回答by joe_doe

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

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

回答by woot

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'

回答by adi gunawan

just add 'staticmethod' decorator to function and problem is fixed

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

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

回答by lukeaus

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

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

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


def myfunc(foo, bar):
    ...

回答by Aaditya Ura

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 argumentyou can read in detail about here Arguments and Parameter in python

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)

since we have three parameters :

因为我们有三个参数:

a is positional parameter

a 是位置参数

b=1 is keyword and default parameter

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

*args is variable length parameter

*args 是可变长度参数

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 :

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

one is positional value: a=1

一个是位置值:a=1

second is keyworded value which is a=12

第二个是关键字值,即 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)

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

additional information

附加信息

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

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

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

那么我们可以这样做
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}

回答by unlockme

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.

“火”已被接受到“酒吧”的论点中。然而,kwargs 中还存在另一个“bar”参数。

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

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