Closures zijn een krachtig mechanisme in Python dat het mogelijk maakt om functies te creëren met "onthouden" gegevens uit de omringende context.
In functionele talen en in Python zijn functies eerste-klassobjekten. Een functie kan een nieuwe functie retourneren die variabelen uit zijn omringende (externe) scope "sluit".
Ontwikkelaars raken vaak in de war over hoe precies gesloten variabelen "leven" binnen een closure, wanneer ze worden gelezen of geschreven, en hoe ze veilig mee om moeten gaan (vooral met mutabele objecten).
Als de interne functie variabelen van de externe functie gebruikt, worden deze automatisch "onthouden" — zelfs als de externe functie al is afgelopen. Voor het lezen van een variabele is dit duidelijk, maar als je de waarde wilt wijzigen, moet je het sleutelwoord nonlocal gebruiken. Bij het werken met mutabele objecten (lijsten, dicts) is dit een bijzondere risicosituatie.
Voorbeeld:
def outer(): count = 0 def inner(): nonlocal count count += 1 return count return inner counter = outer() print(counter()) # 1 print(counter()) # 2
Belangrijkste kenmerken:
nonlocal voor het wijzigen van gesloten variabelen (anders creëert de bewerking een lokale variabele).Is het mogelijk om de waarde van een gesloten variabele binnen een functie te wijzigen zonder nonlocal?
Nee. Als je probeert een nieuwe waarde toe te wijzen zonder nonlocal te vermelden, beschouwt Python dit als het creëren van een nieuwe lokale variabele, en de oude waarde zal niet naar buiten komen.
Voorbeeld:
def make_counter(): count = 0 def inner(): count += 1 # OnboundLocalError! return count return inner
Is het mogelijk om argumenten naar de externe scope door te geven via closure?
Ja, de closure "onthoudt" alle variabelen die beschikbaar zijn in de externe scope, inclusief klasse-attributen, globale variabelen, enz. Maar het wijzigen van deze variabelen vereist bijzondere inspanningen (bijvoorbeeld het gebruik van nonlocal of global).
Wat gebeurt er met mutabele objecten binnen een closure?
Als een closed variabele een verwijzing naar een mutabel object, bijvoorbeeld een lijst, bevat, kun je de inhoud ervan zonder nonlocal wijzigen, maar als je probeert de variabele opnieuw te verwijzen, is nonlocal vereist.
Voorbeeld:
def make_appender(): result = [] def append(x): result.append(x) # Kan! return result return append f = make_appender() print(f(1)) # [1] print(f(2)) # [1, 2]
nonlocal.Een ontwikkelaar schrijft een closure en wijzigt een variabele zonder nonlocal — dit leidt tot een UnboundLocalError.
Voordelen:
Nadelen:
nonlocal.Expliciet gebruik van nonlocal voor beheerde toestand in de closure.
Voordelen:
Nadelen: