Verständnisfrage Parameter mit default Wert

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Benutzeravatar
ThomasL
User
Beiträge: 1366
Registriert: Montag 14. Mai 2018, 14:44
Wohnort: Kreis Unna NRW

Wer von den Profis kann mir das erklären?
Dieser Code

Code: Alles auswählen

def f(a, L=[]):
    L.append(a)
    return L

f(1, [])
f(2, [])
print(f(3, []))
liefert als Ausgabe Warum bekommt man als Ausgabe

Code: Alles auswählen

[1,2,3]
wenn man die leere Liste als Argument weglässt?

Code: Alles auswählen

f(1)
f(2)
print(f(3))
Warum wird die Zuweisung einer leeren Liste an L beim wiederholten Aufruf der Funktion f "ignoriert"?
Beim ersten Mal wird der Defaultwert ja genommen, sonst gebe es ja einen Fehler.
Ich bin Pazifist und greife niemanden an, auch nicht mit Worten.
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

Die Objekte für die Defaultwerte werden zum Zeitpunkt der Definition erzeugt, das ist also äquivalent zu:

Code: Alles auswählen

globales_L = {}
def f(a, L=globales_L):
    L.append(a)
    return L
man hat also eine globale Variable, und wie bei allen globalen Variablen gilt, es sollte sie nicht geben, das bedeutet, dass man Defaultwert-Objekte nicht verändern sollte.
Benutzeravatar
sparrow
User
Beiträge: 4187
Registriert: Freitag 17. April 2009, 10:28

Das mit dem "Initialisieren bei Definition zur Laufzeit" fällt einem immer dann auf die Füße, wenn es keine einfache Wertzuweisung ist. Bei Collections, aber auch bei dem Rückgabewert von Funktionen.
Ich bin da mal irgendwann schmerzlich drüber gestolpert, als ich in einer Funktion den aktuellen Zeitpunkt als Default-Wert brauchte und der entsprechende aufruf von time.time() nur einmal, nämlich während der Definition der Funktion im Interpreter ausgewertet wurde.

Ich löse das so:

Code: Alles auswählen

def f(a, L=None):
    L = [] if L is None else L
    L.append(a)
    return L
Benutzeravatar
ThomasL
User
Beiträge: 1366
Registriert: Montag 14. Mai 2018, 14:44
Wohnort: Kreis Unna NRW

Vielen Dank, jetzt bin ich wieder etwas schlauer.
Habe mal ein print(id(L)) in die Funktion eingefügt
und ohne die leere Liste als 2.tes Argument wird immer die gleiche Id der leeren Default-Liste ausgegeben.
Faszinierend! :-)
Ich bin Pazifist und greife niemanden an, auch nicht mit Worten.
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
Antworten