In Python is een closure een functie die de waarden van externe variabelen "onthoudt", zelfs als deze buiten hun scope wordt aangeroepen. Closures worden gecreëerd wanneer de interne functie verwijst naar variabelen die in de externe functie zijn gedefinieerd. Om dergelijke variabelen vanuit de geneste functie in Python 3 te wijzigen, gebruik je het sleutelwoord nonlocal.
Voorbeeld:
def make_accumulator(): total = 0 def add(value): nonlocal total total += value return total return add acc = make_accumulator() print(acc(10)) # 10 print(acc(5)) # 15
Zonder nonlocal zou de variabele total niet wijzigbaar zijn (UnboundLocalError).
Vraag: "Is het mogelijk om binnen een geneste functie een variabele van de buitenste functie te verhogen zonder het sleutelwoord nonlocal?"
Antwoord: Nee, zonder nonlocal leidt dit tot een fout, aangezien de interpreter de variabele als lokaal voor de geneste functie beschouwt. Voorbeeld:
def outer(): count = 0 def inner(): count += 1 # Fout UnboundLocalError return count return inner
Verhaal In een webapplicatie wilde men een teller lokaal implementeren voor elke handler via geneste functies, maar men vergat
nonlocalte gebruiken. De teller gaf altijd 1 terug, omdat hij count in de lokale ruimte telde en een nieuwe creëerde, niet gerelateerd aan de externe closure.
Verhaal Bij parallelle taken (multithreading) worden vaak closures en lambdas gebruikt. Zonder begrip van closures ontstond een situatie waarin alle lambda-functies het laatste waarde van de loopvariabele "onkruid" omkeerden, en de opdrachten elkaar kopieerden in plaats van verschillende taken te verwerken.
Verhaal Bij het schrijven van een decorator zonder de juiste closure (er werden geen parameters naar de externe scope doorgegeven) ontstond een situatie waarin de decorator geen toestand tussen aanroepen kon accumuleren, wat leidde tot onverwachte resultaten en onbetrouwbare werking van de applicatie.