Manchmal scheint es natürlich, einen Standardparameter zu haben, der eine leere Liste ist. Doch Python gibt ein unerwartetes Verhalten in diesen Situationen .
Wenn ich zum Beispiel eine Funktion habe:
def my_func(working_list = []):
working_list.append("a")
print(working_list)
Das erste Mal, wenn es als Standard aufgerufen wird, funktioniert, aber Anrufe danach aktualisieren die vorhandene Liste (mit einem "a" pro Anruf) und drucken die aktualisierte Version.
Was ist also der pythonische Weg, um das gewünschte Verhalten zu erreichen (eine neue Liste bei jedem Anruf)?
python
python-3.x
John Mulder
quelle
quelle
Antworten:
In den Dokumenten wird angegeben, dass Sie diese
None
als Standard verwenden und im Hauptteil der Funktion explizit testen sollten .quelle
f()
eine Liste aufrufen möchten, müssen Sief(*l)
die Bruttoliste aufrufen . Schlimmer noch, die Implementierungmate(['larch', 'finch', 'robin'], ['bumble', 'honey', 'queen'])
würde mit varargs SAUGEN. Viel besser, wenn es so istdef mate(birds=[], bees=[]):
.Bestehende Antworten haben bereits die gewünschten direkten Lösungen geliefert. Da dies jedoch eine sehr häufige Gefahr für neue Python-Programmierer ist, lohnt es sich, die Erklärung hinzuzufügen, warum sich Python so verhält, die im " Per Anhalter durch Python " als "veränderbare Standardargumente " zusammengefasst ist: http: // docs .python-guide.org / de / latest / writing / gotchas /
Zitat: " Die Standardargumente von Python werden einmal ausgewertet, wenn die Funktion definiert wird, nicht jedes Mal, wenn die Funktion aufgerufen wird (wie beispielsweise Ruby). Dies bedeutet, dass Sie, wenn Sie ein veränderliches Standardargument verwenden und es mutieren, dies tun und haben werden." mutierte dieses Objekt auch für alle zukünftigen Aufrufe der Funktion "
Beispielcode zur Implementierung:
quelle
Nicht, dass es in diesem Fall wichtig wäre, aber Sie können die Objektidentität verwenden, um auf Keine zu testen:
Sie können auch die Vorteile des booleschen Operators oder der Definition in Python nutzen:
Dies verhält sich jedoch unerwartet, wenn der Anrufer Ihnen eine leere Liste (die als falsch gilt) als Arbeitsliste gibt und erwartet, dass Ihre Funktion die Liste ändert, die er ihr gegeben hat.
quelle
Wenn die Absicht der Funktion darin besteht, den als übergebenen Parameter zu ändern
working_list
, lesen Sie die Antwort von HenryR (= Keine, prüfen Sie, ob darin Keine vorhanden ist).Wenn Sie das Argument jedoch nicht mutieren wollten, verwenden Sie es einfach als Ausgangspunkt für eine Liste. Sie können es einfach kopieren:
(oder in diesem einfachen Fall nur,
print starting_list + ["a"]
aber ich denke, das war nur ein Spielzeugbeispiel)Im Allgemeinen ist das Mutieren Ihrer Argumente in Python ein schlechter Stil. Die einzigen Funktionen, von denen vollständig erwartet wird, dass sie ein Objekt mutieren, sind Methoden des Objekts. Es ist noch seltener, ein optionales Argument zu mutieren - ist ein Nebeneffekt, der nur bei einigen Aufrufen auftritt, wirklich die beste Schnittstelle?
Wenn Sie dies aus der C-Gewohnheit der "Ausgabeargumente" heraus tun, ist dies völlig unnötig - Sie können immer mehrere Werte als Tupel zurückgeben.
Wenn Sie dies tun, um eine lange Liste von Ergebnissen effizient zu erstellen, ohne Zwischenlisten zu erstellen, sollten Sie sie als Generator schreiben und verwenden,
result_list.extend(myFunc())
wenn Sie sie aufrufen. Auf diese Weise bleiben Ihre Anrufkonventionen sehr sauber.Ein Muster, bei dem häufig ein optionales Argument mutiert wird , ist ein verstecktes "Memo" -Arg in rekursiven Funktionen:
quelle
Ich bin vielleicht nicht zum Thema gehörend, aber denken Sie daran, dass die pythonische Methode darin besteht, ein Tupel
*args
oder ein Wörterbuch zu übergeben, wenn Sie nur eine variable Anzahl von Argumenten übergeben möchten**kargs
. Diese sind optional und besser als die SyntaxmyFunc([1, 2, 3])
.Wenn Sie ein Tupel übergeben möchten:
Wenn Sie ein Wörterbuch übergeben möchten:
quelle
Es wurden bereits gute und korrekte Antworten gegeben. Ich wollte nur eine andere Syntax angeben, um zu schreiben, was Sie tun möchten, was ich schöner finde, wenn Sie beispielsweise eine Klasse mit standardmäßigen leeren Listen erstellen möchten:
Dieses Snippet verwendet die if else-Operatorsyntax. Ich mag es besonders, weil es ein hübscher kleiner Einzeiler ohne Doppelpunkte usw. ist und sich fast wie ein normaler englischer Satz liest. :) :)
In deinem Fall könntest du schreiben
quelle
Ich habe die UCSC-Erweiterungsklasse belegt
Python for programmer
Was gilt für: def Fn (data = []):
Antworten:
quelle