class方法生成“TypeError:...为关键字参数获取多个值...”

时间:2013-09-23 00:08:46

标签: python class python-2.7 methods

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

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'

发生了什么事?

7 个答案:

答案 0 :(得分:153)

问题是传递给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"分配给thing,因此异常。

要演示,请尝试使用原始代码运行:

myfoo.foodo("something")
print
print myfoo

您输出如下:

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

<__main__.foo object at 0x321c290>

你可以看到'thing'被分配了对'foo'类的实例'myfoo'的引用。 This section文档解释了函数参数的工作原理。

答案 1 :(得分:48)

感谢有启发性的帖子。我只想留言,如果你得到&#34; TypeError:foodo()获得了关键字参数&#39; thing&#39;&#34;的多个值,它也可能是因为你错误地传递了自我&#39;作为调用函数时的参数(可能是因为你从类声明中复制了这一行 - 当一个人赶时间时,这是一个常见错误)。

答案 2 :(得分:26)

这可能是显而易见的,但它可能对以前从未见过它的人有所帮助。如果您错误地按位置分配参数并明确地按名称分配参数,这也适用于常规函数。

var promises = logCspItemInventoryStatus(payload,result.cspItems);

    return $q.all(promises)
    .then(function(result){
      toastr.success('Items have been logged');
    })
   .catch(function(err){
     toastr.error(err);
   })

var logCspItemInventoryStatus = function (payload,cspItems) {
var promises = [];
 angular.forEach(cspItems, function(item){
      //I am appending payload with items
       var payloadCopy = angular.copy(payload);
       payloadCopy.qty=item.checking;
       payloadCopy.description=item.description;

      //payload 1 {docId: "55c124f7485684e81d6181fc", by: "Foo Bar", checkIn: false, qty: 2, description: "car"}
      //payload 2 {docId: "55c124f7485684e81d6181fc", by: "Foo2 Bar2", checkIn: false, qty: 1, description: "hall"}

       var p = checkOutCspItem(payloadCopy);
      promises.push(p);
});

return promises;
 };

//returns a promise
var checkOutData = function(payload) {
  return Csp.update(payload).$promise.then(function(result) {
return result.data
   });
  }

答案 3 :(得分:7)

只需将'staticmethod'装饰器添加到功能中,问题就解决了

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

答案 4 :(得分:3)

我想再补充一个答案:

  

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

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是可变长度参数

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

一个是位置值:a = 1

秒是keyworded值,即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 :(得分:2)

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

>>> 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'
>>> 
“火”已被接受进入'bar'论证。然而,在kwargs中还有另一个“酒吧”论点。

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

答案 6 :(得分:1)

如果你使用jquery ajax来反转到一个不包含'request'参数的函数,那么在Django中也会发生这种情况

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


def myfunc(foo, bar):
    ...