Wenn ich eine Klassenmethode mit einem Schlüsselwortargument so definiere:
class foo(object):
def foodo(thing=None, thong='not underwear'):
print thing if thing else "nothing"
print 'a thong is',thong
Durch Aufrufen der Methode wird Folgendes generiert TypeError
:
myfoo = foo()
myfoo.foodo(thing="something")
...
TypeError: foodo() got multiple values for keyword argument 'thing'
Was ist los?
python
class
python-2.7
methods
drevicko
quelle
quelle
self
besser als implizit istthis
.Antworten:
Das Problem ist, dass das erste Argument, das in Python an Klassenmethoden übergeben wird, immer eine Kopie der Klasseninstanz ist, auf der die Methode aufgerufen wird, normalerweise mit der Bezeichnung
self
. Wenn die Klasse folgendermaßen deklariert ist:es verhält sich wie erwartet.
Erläuterung:
Ohne
self
als ersten Parametermyfoo.foodo(thing="something")
wird diefoodo
Methode bei der Ausführung mit Argumenten aufgerufen(myfoo, thing="something")
. Die Instanzmyfoo
wird dann zugewiesenthing
(dathing
der erste deklarierten Parameter ist), aber auch Versuche Python zuzuweisen ,"something"
umthing
somit die Ausnahme.Versuchen Sie dies zu demonstrieren mit dem Originalcode:
Sie werden wie folgt ausgeben:
Sie können sehen, dass 'thing' ein Verweis auf die Instanz 'myfoo' der Klasse 'foo' zugewiesen wurde. In diesem Abschnitt der Dokumentation wird erläutert, wie Funktionsargumente etwas besser funktionieren.
quelle
Danke für die lehrreichen Beiträge. Ich möchte nur darauf hinweisen, dass wenn Sie "TypeError: foodo () hat mehrere Werte für das Schlüsselwortargument 'thing'" erhalten, es auch sein kann, dass Sie fälschlicherweise das 'self' als Parameter übergeben, wenn Aufruf der Funktion (wahrscheinlich, weil Sie die Zeile aus der Klassendeklaration kopiert haben - dies ist ein häufiger Fehler, wenn Sie es eilig haben).
quelle
@classmethod
, die Lösung zu verwenden ist ,super().function(...)
statt<parentclass>.function(cls, ...)
.Dies mag offensichtlich sein, aber es könnte jemandem helfen, der es noch nie zuvor gesehen hat. Dies gilt auch für reguläre Funktionen, wenn Sie einen Parameter fälschlicherweise nach Position und explizit nach Namen zuweisen.
quelle
Fügen Sie einfach den Dekorator 'staticmethod' zur Funktion hinzu, und das Problem ist behoben
quelle
myfoo.foodo(thing="something")
, wird thing = "etwas" eher dem ersten Argument als dem impliziten Selbstargument zugewiesen.self
Ich möchte noch eine Antwort hinzufügen:
there is difference between parameter and argument
Sie können hier ausführlich Argumente und Parameter in Python lesenda wir drei Parameter haben:
a ist Positionsparameter
b = 1 ist Schlüsselwort und Standardparameter
* args ist ein Parameter variabler Länge
Also weisen wir zuerst einen als Positionsparameter zu, dh wir müssen dem Positionsargument in seiner Positionsreihenfolge einen Wert geben, hier ist die Reihenfolge von Bedeutung. Wir übergeben jedoch Argument 1 an der Stelle einer aufrufenden Funktion und geben dann auch einen Wert für a an, der als Schlüsselwortargument behandelt wird. Jetzt haben zwei Werte:
Eins ist der Positionswert: a = 1
Der zweite Wert ist der Schlüsselwortwert a = 12
Lösung
Wir müssen zu wechseln
hello(1, 2, 3, 4,a=12)
,hello(1, 2, 3, 4,12)
damit a jetzt nur einen Positionswert erhält, der 1 ist, und b den Wert 2 erhält und der Rest der Werte * args (Parameter variabler Länge) erhält.zusätzliche Information
wenn wir wollen, dass * args 2,3,4 und a 1 und b 12 erhalten
dann können wir so machen
def hello(a,*args,b=1): pass hello(1, 2, 3, 4,b=12)
Etwas mehr :
Ausgabe :
quelle
Dieser Fehler kann auch auftreten, wenn Sie ein Schlüsselwortargument übergeben, für das einer der Schlüssel einem Positionsargument ähnlich ist (denselben Zeichenfolgennamen hat).
"Feuer" wurde in das Argument "Bar" aufgenommen. Und doch gibt es in kwargs noch ein weiteres 'bar'-Argument.
Sie müssten das Schlüsselwortargument aus den kwargs entfernen, bevor Sie es an die Methode übergeben.
quelle
Dies kann auch in Django passieren, wenn Sie jquery ajax verwenden, um eine URL zu erstellen, die zu einer Funktion umkehrt, die keinen 'request'-Parameter enthält
quelle