Het begrijpen van hoe Python argumenten naar functies overdraagt, is van cruciaal belang om onverwachte gegevenswijzigingen te voorkomen en om correcte code-ontwerpen te maken.
In traditionele programmeertalen, zoals C of Java, wordt argumentoverdracht per waarde (copy by value) of per referentie (copy by reference) gebruikt. In Python is er echter een ander model — call by object reference (soms "call by sharing" genoemd).
Veel ontwikkelaars denken ten onrechte dat Python altijd argumenten per referentie of per waarde overdraagt. Dit leidt onvermijdelijk tot situaties waarin wijzigbare objecten onverwacht worden aangepast in de aanroepende code.
In Python zijn de waarden van de functieparameters verwijzingen naar de objecten die aan de functie zijn doorgegeven. Dit betekent:
Voorbeeld:
# lijst - wijzigbaar (mutable) def add_item(lst): lst.append(42) mijn_lijst = [1, 2, 3] add_item(mijn_lijst) print(mijn_lijst) # [1, 2, 3, 42] # int - onwijzigbaar (immutable) def add_num(x): x = x + 1 num = 10 add_num(num) print(num) # 10
Belangrijke kenmerken:
Worden argumenten in Python altijd per referentie doorgegeven?
Nee, in Python worden verwijzingen naar objecten doorgegeven, en hoe het object zich gedraagt, hangt af van of het wijzigbaar is of niet. Een onwijzigbaar object creëert altijd een nieuw object bij een wijziging.
Kan ik een wijzigbaar argument in een functie opnieuw toewijzen, zodat het invloed heeft op het externe object?
Nee. Als je binnen de functie een nieuwe waarde aan de parameter toewijst, verandert het externe object niet — je verandert alleen de lokale verwijzing.
Voorbeeld:
def reassign_list(lst): lst = [99, 100] mijn_lijst = [1, 2, 3] reassign_list(mijn_lijst) print(mijn_lijst) # [1, 2, 3]
Waarom kan een functie die standaard een lijst accepteert, vreemd gedrag vertonen bij herhaalde aanroepen?
Omdat de standaardwaarde slechts één keer wordt gemaakt — bij de definitie van de functie, en als deze wordt gewijzigd (bijvoorbeeld door een element toe te voegen), zal het voor alle volgende aanroepen veranderen.
def add_element(x, cache=[]): cache.append(x) return cache print(add_element(1)) # [1] print(add_element(2)) # [1, 2]
Een programmeur geeft een lijst door aan een functie en verwacht dat zijn originele lijst niet zal veranderen, maar de functie voegt een element toe.
Voordelen:
Nadelen:
Een programmeur kopieert de lijst expliciet binnen de functie, indien nodig om iets terug te geven, maar niet om het origineel te wijzigen:
def process_data(data): data = data.copy() # of list(data) # veilige bewerkingen met de kopie data.append('rapport') return data
Voordelen:
Nadelen: