Veränderliche Standardargumente

Wenn man in Python veränderliche Argumente mit Standardargumenten kombiniert, kann das zu unerwarteten Ergebnissen führen.
Lassen Sie uns dies mit einem einfachen Beispiel veranschaulichen. Angenommen, Sie sind Lehrer und möchten eine Funktion erstellen, um die Noten der Schüler für verschiedene Aufgaben zu erfassen. Sie möchten eine Liste verwenden, um diese Noten zu verfolgen. Also könnten Sie zunächst etwa Folgendes schreiben:
def record_score(new_score, score_list=[]):
    score_list.append(new_score)
    return score_list

print(record_score(95))  # [95]
print(record_score(85))  # [95, 85]
Das scheint zunächst zu funktionieren. Die Funktion record_score akzeptiert eine Punktzahl und eine Liste. Wird keine Liste übergeben, verwendet sie eine leere Liste (das score_list=[] in der Funktionsdefinition).
Wenn Sie record_score(95) aufrufen, scheint die Funktion korrekt zu arbeiten – sie gibt eine Liste mit der Punktzahl 95 zurück. Aber wenn Sie danach record_score(85) aufrufen, gibt die Funktion eine Liste mit 95 und 85 zurück. Es ist, als ob die Funktion sich die Liste vom letzten Aufruf gemerkt hätte.
Das könnte Sie verwundern. In den meisten Programmiersprachen werden beim Beenden einer Funktion alle lokalen Variablen (wie score_list) verworfen und vergessen. Beim nächsten Aufruf der Funktion wird neu begonnen.
In Python ist das Verhalten jedoch anders, wenn ein veränderliches Objekt als Standardargument verwendet wird. Python erstellt das Standardargument nur einmal, nämlich beim Definieren der Funktion. Jedes Mal, wenn Sie record_score ohne eine Liste aufrufen, verwendet Python dieselbe Liste, die es beim ersten Definieren der Funktion erstellt hat. Wenn Sie diese Liste ändern (indem Sie eine Punktzahl anhängen), bleibt die Änderung beim nächsten Aufruf der Funktion bestehen.
In unserer Funktion wird also score_list über alle Funktionsaufrufe hinweg geteilt, bei denen wir keine eigene Liste übergeben. Deshalb sammeln sich in unserem Beispiel die Noten an.
Das ist nicht das, was wir wollten! Wir wollten, dass jeder Aufruf von record_score mit einer leeren Liste beginnt, es sei denn, wir liefern eine eigene Liste.
Um dies zu vermeiden, ist es üblich, None als Standardwert für Argumente zu verwenden, die veränderlich sein könnten. Dann können Sie innerhalb der Funktion ein neues veränderliches Objekt erstellen, wenn das Argument None ist. So könnten Sie die record_score-Funktion schreiben, um das Problem zu umgehen:
def record_score(new_score, score_list=None):
    if score_list is None:  # Falls keine Liste übergeben wurde,
        score_list = []     # erstelle eine neue
    score_list.append(new_score)
    return score_list

print(record_score(95))  # [95]
print(record_score(85))  # [85]
In dieser korrigierten Version erhält jeder Aufruf von record_score, der keine eigene Liste übergibt, eine ganz neue Liste. So werden die Noten nicht über Funktionsaufrufe hinweg geteilt.
💡
Die wichtigste Erkenntnis ist also: Veränderliche Standardargumente in Python können zu unerwartetem Verhalten führen, da sie nur einmal erstellt werden und jedes Mal, wenn die Funktion aufgerufen wird, dasselbe Objekt verwendet wird. Dies ist möglicherweise nicht das, was Sie wollen, insbesondere wenn Sie das veränderliche Objekt ändern. Um dieses Problem zu vermeiden, können Sie None als Standardwert verwenden und bei Bedarf innerhalb der Funktion ein neues Objekt erstellen.
 
To check your solution you need to sign in
Sign in to continue