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?
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.
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é).
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'
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
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
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).
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 çadef 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}
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.
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):
...