web-dev-qa-db-fra.com

La méthode class génère "TypeError: ... obtenu plusieurs valeurs pour l'argument de mot clé ..."

Si je définis une méthode de classe avec un argument de mot clé, procédez comme suit:

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

l'appel de la méthode génère un TypeError:

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

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

Que se passe-t-il?

119
drevicko

Le problème est que le premier argument passé aux méthodes de classe dans python est toujours une copie de l'instance de la classe sur laquelle la méthode est appelée, généralement appelée self. Si la classe est déclarée ainsi:

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

il se comporte comme prévu.

Explication:

Sans self comme premier paramètre, lorsque myfoo.foodo(thing="something") est exécuté, la méthode foodo est appelée avec les arguments (myfoo, thing="something"). L'instance myfoo est alors affectée à thing (puisque thing est le premier paramètre déclaré), mais python tente également d'assigner "something" à thing, d’où l’exception.

Pour démontrer, essayez d’exécuter ceci avec le code original:

myfoo.foodo("something")
print
print myfoo

Vous produirez comme:

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

<__main__.foo object at 0x321c290>

Vous pouvez voir que "chose" a été affecté à l'instance "myfoo" de la classe "foo". Cette section de la documentation explique comment les arguments de fonction fonctionnent un peu plus.

158
drevicko

Merci pour les messages instructifs. Je voudrais juste garder une note que si vous obtenez "TypeError: foodo () a plusieurs valeurs pour l'argument de mot clé" chose "", il se peut également que vous passiez à tort le "self" comme paramètre lorsque appel de la fonction (probablement parce que vous avez copié la ligne de la déclaration de classe - c'est une erreur courante quand on est pressé).

48
joe_doe

Cela peut paraître évident, mais cela pourrait aider quelqu'un qui ne l'a jamais vu auparavant. Cela se produit également pour les fonctions standard si vous affectez par erreur un paramètre par position et explicitement par nom.

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

il suffit d'ajouter le décorateur 'staticmethod' au fonctionnement et le problème est résolu

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

Je veux ajouter une autre réponse:

Cela se produit lorsque vous essayez de passer un paramètre de position avec un ordre de position incorrect, ainsi qu'un argument de mot clé dans l'appel de fonction.

there is difference between parameter and argument vous pouvez lire en détail ici Arguments et paramètres en python

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


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

puisque nous avons trois paramètres:

un paramètre de position

b = 1 est le mot clé et le paramètre par défaut

* args est un paramètre de longueur variable

nous affectons donc d’abord un paramètre as positional, ce qui signifie que nous devons donner une valeur à l’argument positionnel dans son ordre de position, ici l’importance. mais nous passons l'argument 1 à la place d'une fonction d'appel, puis nous donnons également de la valeur à a, en tant qu'argument de mot clé. maintenant a deux valeurs:

on est la valeur de position: a = 1

la seconde est la valeur associée à un mot clé qui est a = 12

Solution

Nous devons changer hello(1, 2, 3, 4,a=12) en hello(1, 2, 3, 4,12) pour que maintenant a obtienne une seule valeur de position, 1, b, 2 et le reste des valeurs obtienne * args (paramètre de longueur variable).

information additionnelle

si nous voulons que * args devrait avoir 2,3,4 et a devrait obtenir 1 et b devrait avoir 12

alors on peut faire comme ça
def hello(a,*args,b=1): pass hello(1, 2, 3, 4,b=12)

Quelque chose de plus :

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

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

sortie:

1

(2, 1, 2, 8, 9)

1

{'c': 12}
4
Aaditya Ura

Cette erreur peut également se produire si vous passez un argument de clé pour lequel l'une des clés est similaire (a le même nom de chaîne) à un argument de position.

>>> 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" a été accepté dans l'argument 'bar'. Et pourtant, il existe un autre argument 'bar' dans kwargs.

Avant de le transmettre à la méthode, vous devez supprimer le mot clé argument du mot clé kwargs.

2
unlockme

Cela peut aussi arriver dans Django si vous utilisez jquery ajax en url qui retourne à une fonction qui ne contient pas le paramètre 'request'

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


def myfunc(foo, bar):
    ...
1
lukeaus