Jeder, der lange genug an Python bastelt, wurde von folgendem Problem gebissen (oder in Stücke gerissen):
def foo(a=[]):
a.append(5)
return a
Python-Neulinge würden erwarten, dass diese Funktion immer eine Liste mit nur einem Element zurückgibt : [5]
. Das Ergebnis ist stattdessen sehr unterschiedlich und sehr erstaunlich (für einen Anfänger):
>>> foo()
[5]
>>> foo()
[5, 5]
>>> foo()
[5, 5, 5]
>>> foo()
[5, 5, 5, 5]
>>> foo()
Ein Manager von mir hatte einmal seine erste Begegnung mit dieser Funktion und nannte sie "einen dramatischen Designfehler" der Sprache. Ich antwortete, dass das Verhalten eine zugrunde liegende Erklärung habe, und es ist in der Tat sehr rätselhaft und unerwartet, wenn Sie die Interna nicht verstehen. Ich konnte jedoch die folgende Frage (für mich selbst) nicht beantworten: Was ist der Grund für die Bindung des Standardarguments bei der Funktionsdefinition und nicht bei der Funktionsausführung? Ich bezweifle, dass das erlebte Verhalten einen praktischen Nutzen hat (wer hat wirklich statische Variablen in C verwendet, ohne Fehler zu züchten?)
Bearbeiten :
Baczek machte ein interessantes Beispiel. Zusammen mit den meisten Ihrer Kommentare und insbesondere von Utaal habe ich weiter ausgeführt:
>>> def a():
... print("a executed")
... return []
...
>>>
>>> def b(x=a()):
... x.append(5)
... print(x)
...
a executed
>>> b()
[5]
>>> b()
[5, 5]
Mir scheint, dass die Entwurfsentscheidung relativ dazu war, wo der Umfang der Parameter platziert werden sollte: innerhalb der Funktion oder "zusammen" damit?
Das Binden innerhalb der Funktion würde bedeuten, dass x
es effektiv an den angegebenen Standard gebunden ist, wenn die Funktion aufgerufen und nicht definiert wird, was einen tiefen Fehler darstellen würde: Die def
Linie wäre "hybrid" in dem Sinne, dass ein Teil der Bindung (von Das Funktionsobjekt würde bei der Definition und der Teil (Zuweisung von Standardparametern) zum Zeitpunkt des Funktionsaufrufs erfolgen.
Das tatsächliche Verhalten ist konsistenter: Alles in dieser Zeile wird ausgewertet, wenn diese Zeile ausgeführt wird, dh bei der Funktionsdefinition.
[5]
" Ich bin ein Python - Neuling, und ich würde dies nicht erwarten, denn offensichtlich foo([1])
wird zurückkehren [1, 5]
, nicht [5]
. Was Sie damit sagen wollten, ist, dass ein Anfänger erwarten würde, dass die ohne Parameter aufgerufene Funktion immer zurückkehrt [5]
.