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

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

Ответ 1

Проблема в том, что первый аргумент, переданный методам класса в 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". Этот раздел в документах объясняет, как аргументы функции работают немного больше.

Ответ 2

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

Ответ 3

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

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

Ответ 4

просто добавьте декоратор "staticmethod" в функцию и проблема исправлена.

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

Ответ 5

Я хочу добавить еще один ответ:

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

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

поэтому мы сначала назначаем как позиционный параметр, означает, что мы должны предоставить значение позиционному аргументу в его порядке позиции, здесь задайте вопрос. но мы передаем аргумент 1 в месте функции вызова, а затем мы также предоставляем значение a, рассматривая как аргумент ключевого слова. теперь a имеют два значения:

one - это позиционное значение: a = 1

second - ключевое слово, которое равно 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}

Ответ 6

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

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


def myfunc(foo, bar):
    ...

Ответ 7

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

>>> 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, прежде чем передать его методу.