Mutabilität definiert, ob ein Objekt verändert werden kann, ohne seine Identität (Speicheradresse) zu ändern:
Einfluss auf Funktionen:
Beispiel:
def f(lst): lst.append(42) data = [] f(data) print(data) # [42] def f2(x): x += 1 n = 1 f2(n) print(n) # 1
"Was gibt der folgende Code aus?"
def foo(bar=[]): bar.append(1) return bar print(foo()) print(foo())
Antwort: Gibt aus:
[1]
[1, 1]
Weil die Funktion-Argumente einmal bei der Definition initialisiert werden, nicht bei jedem Aufruf. Listen (und andere mutable Objekte) in Funktionsargumenten sind eine beliebte Falle.
Geschichte
In einer REST-API wurde eine Liste über eine Funktion mit einem Standardparameter zurückgegeben:
def get_default_items(items=[]): items.append('x') return items
Nach einigen Aufrufen stellte man fest, dass die Liste wuchs, obwohl nur ein Element erwartet wurde.
Geschichte
In einer Funktion planten wir, einen String zu "ersetzen":
def replace_word(word): word.replace('a', 'b') word = 'data' replace_word(word) print(word) # Erwartet 'dbtb', erhielt 'data'
String-Methoden ändern den ursprünglichen String nicht, sondern geben einen neuen zurück, aber der Rückgabewert wurde ignoriert.
Geschichte
Bei der Arbeit mit verschachtelten Strukturen:
original = [[1, 2], [3, 4]] copy = original[:] copy[0][0] = -1 print(original) # [[-1, 2], [3, 4]]
Hier wurde eine flache Kopie verwendet, in der Annahme, dass nur die Kopie geändert wurde, aber die inneren Objekte blieben gemeinsam.