Mutabiliteit bepaalt of een object kan worden gewijzigd zonder de identificatie (adres in het geheugen) te veranderen:
Invloed op functies:
Voorbeeld:
def f(lst): lst.append(42) data = [] f(data) print(data) # [42] def f2(x): x += 1 n = 1 f2(n) print(n) # 1
"Wat zal de volgende code uitgeven?"
def foo(bar=[]): bar.append(1) return bar print(foo()) print(foo())
Antwoord: Geeft het volgende:
[1]
[1, 1]
Omdat de argumenten van de functie slechts één keer worden geïnitialiseerd bij de definitie, en niet bij elke aanroep. Lijsten (en andere mutabele objecten) in functieargumenten zijn een populaire valstrik.
Verhaal
In de REST API werd een lijst teruggegeven via een functie met een standaardparameter:
def get_default_items(items=[]): items.append('x') return items
Na enkele aanroepen ontdekten we dat de lijst groeide, terwijl we alleen één element verwachtten.
Verhaal
We wilden in een functie een string "veranderen":
def replace_word(word): word.replace('a', 'b') word = 'data' replace_word(word) print(word) # Verwachtte 'dbtb', kreeg 'data'
De str-methoden wijzigen de oorspronkelijke string niet, maar geven een nieuwe terug, maar de waarde van het teruggegeven resultaat werd genegeerd.
Verhaal
Bij het werken met geneste structuren:
original = [[1, 2], [3, 4]] copy = original[:] copy[0][0] = -1 print(original) # [[-1, 2], [3, 4]]
We gebruikten oppervlakkige kopieerroutine, denkend dat we alleen de kopie hadden gewijzigd, maar geneste objecten bleven gemeenschappelijk.