метод класса генерирует "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'

что происходит?

7 105

7 ответов:

проблема в том, что первый аргумент, передаваемый методам класса в 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>

вы можете видеть, что "вещь" была назначена ссылка на экземпляр "myfoo" класса "foo". в этом разделе из документов объясняет, как аргументы функции работают немного больше.

Спасибо за поучительные посты. Я просто хотел бы отметить, что если вы получаете "TypeError: foodo() получил несколько значений для ключевого аргумента" thing", Это также может быть, что вы ошибочно передаете "self" в качестве параметра при вызове функции (вероятно, потому, что вы скопировали строку из объявления класса - это распространенная ошибка, когда кто-то спешит).

это может быть очевидно, но это может помочь тому, кто никогда не видел его раньше. Это также происходит для обычных функций, если вы ошибочно назначаете параметр по позиции и явно по имени.

>>> 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" в функцию, и проблема исправлена

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-позиционный параметр

Б=1 ключевое слово и параметр по умолчанию

*args-параметр переменной длины

поэтому мы сначала назначаем как позиционный параметр, значит, мы должны предоставить значение позиционному аргументу в его порядке расположения, здесь порядок имеет значение. но мы передаем аргумент 1 в место A в вызывающей функции , а затем мы также предоставляем значение 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}

эта ошибка также может произойти, если вы передаете аргумент ключевого слова, для которого один из ключей похож (имеет такое же имя строки) на позиционный аргумент.

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

вам нужно будет удалить аргумент ключевого слова из kwargs перед передачей его в метод.

также это может произойти в Django, если вы используете jQuery ajax для url, который обращается к функции, которая не содержит параметр 'request'

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


def myfunc(foo, bar):
    ...