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: 767
Registriert: Montag 14. Mai 2018, 14:44
Wohnort: Kreis Unna NRW

Donnerstag 13. Juni 2019, 19:14

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: 10524
Registriert: Sonntag 21. Oktober 2012, 17:20

Donnerstag 13. Juni 2019, 19:21

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: 1359
Registriert: Freitag 17. April 2009, 10:28

Donnerstag 13. Juni 2019, 19:33

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: 767
Registriert: Montag 14. Mai 2018, 14:44
Wohnort: Kreis Unna NRW

Donnerstag 13. Juni 2019, 19:46

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