ProgrammatieBackend ontwikkelaar

Wat is argumentoverdracht per referentie en per waarde in Python? Hoe implementeert Python dit mechanisme en waarom is het belangrijk om ze te onderscheiden bij het ontwerpen van functies?

Slaag voor sollicitatiegesprekken met de Hintsage AI-assistent

Antwoord.

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.

Geschiedenis van de vraag

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).

Probleem

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.

Oplossing

In Python zijn de waarden van de functieparameters verwijzingen naar de objecten die aan de functie zijn doorgegeven. Dit betekent:

  • Als het object wijzigbaar (mutable: lijst, dict, set…) is, kan het binnen de functie worden gewijzigd, en dit zal buiten zichtbaar zijn.
  • Als het object onwijzigbaar (immutable: int, str, tuple, frozenset) is, zal een poging om het binnen de functie te wijzigen resulteren in het creëren van een nieuw object en niet het externe object beïnvloeden.

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:

  • Wijzigbare objecten kunnen binnen de functie worden gewijzigd — deze wijzigingen zijn buiten zichtbaar.
  • Onwijzigbare objecten worden niet beïnvloed door de functie — er worden alleen nieuwe objecten gemaakt.
  • Python kopieert nooit automatisch argumenten, zelfs wijzigbare structuren worden altijd "per referentie" doorgegeven.

Vragen met een valstrik.

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]

Typische fouten en anti-patronen

  • Het gebruik van wijzigbare standaardargumenten (zoals in het laatste voorbeeld).
  • Verwachten dat een functie de doorgegeven lijst of dict niet zal wijzigen, terwijl deze dat wel doet.
  • Het verwarren van de effecten van functies bij het werken met wijzigbare en onwijzigbare objecten.

Voorbeeld uit het leven

Negatieve case

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:

  • Snelle uitvoering, geen gegevenskopieën.

Nadelen:

  • Onverwachte bijwerkingen, bugs in grote code, als iemand niet op de hoogte is van de wijzigingen aan het argument.

Positieve case

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:

  • Geen ongewenste bijeffecten, het origineel is beschermd.

Nadelen:

  • Bij grote objecten — geheugen/tijdskosten voor de kopie.