Python-closures uitgelegd: hoe geneste functies variabelen vangen
Python-closures
Ontdek hoe Python-closures werken, hoe je ze definieert en waarom ze essentieel zijn voor schone, efficiënte code.
Non-lokale variabelen in een geneste functie
Voordat we closures verkennen, is het cruciaal om geneste functies en non-lokale variabelen te begrijpen. Een functie gedefinieerd binnen een andere functie heet een geneste functie. Zulke functies kunnen variabelen lezen uit hun omringende scope.
In Python zijn deze non-lokale variabelen standaard read-only. Om ze te wijzigen, moet je de variabele expliciet declareren als nonlocal binnen de geneste functie.
Hieronder een simpel voorbeeld dat een geneste functie toont die een non-lokale variabele benadert.
def print_bericht(bericht):
# Outer functie
def printer():
# Geneste functie
print(bericht)
printer() # Uitvoeren
print_bericht("Hallo")
Uitvoer
Hallo
De geneste printer()-functie kan de bericht-variabele benaderen uit de outer scope.
Een closure-functie definiëren
Wat als de outer-functie de geneste functie retourneerde in plaats van aan te roepen? De code zou er zo uitzien:
def print_bericht(bericht):
def printer():
print(bericht)
return printer # Retourneer de geneste functie
# Sla de geretourneerde functie op
andere = print_bericht("Hallo")
andere()
Uitvoer
Hallo
Let op dat de functie printer nog steeds de waarde van bericht onthoudt zelfs nadat print_bericht heeft geëindigd. Dit fenomeen – waarbij een functie toegang behoudt tot variabelen uit haar definitiescope – heet een closure in Python.
Om dit verder te illustreren, verwijder de oorspronkelijke functie en zie dat de geretourneerde functie nog steeds werkt:
>>> del print_bericht
>>> andere()
Hallo
>>> print_bericht("Hallo")
Traceback (most recent call last):
... NameError: name 'print_bericht' is not defined
De geretourneerde functie blijft functioneren omdat het de benodigde data in zijn closure vastlegde.
Wanneer hebben we closures?
In Python bestaat een closure wanneer een geneste functie:
- binnen een andere functie gedefinieerd is.
- een variabele uit de omringende functie refereert.
- geretourneerd wordt door de outer-functie.
Wanneer closures gebruiken?
Closures bieden diverse voordelen:
- Ze elimineren de noodzaak voor globale variabelen, wat encapsulatie verbetert.
- Ze bieden een lichtgewicht alternatief voor single-method klassen, wat code beknopt houdt.
- Ze maken functionele patronen mogelijk zoals decorators, waar een wrapper-functie toegang nodig heeft tot de argumenten van de oorspronkelijke functie.
Hieronder een veelvoorkomend voorbeeld: een factory die vermenigvuldigingsfuncties aanmaakt.
def maak_vermenigvuldiger_van(n):
def vermenigvuldiger(x):
return x * n
return vermenigvuldiger
# Maak specifieke vermenigvuldigers
keer3 = maak_vermenigvuldiger_van(3)
keer5 = maak_vermenigvuldiger_van(5)
print(keer3(9)) # 27
print(keer5(3)) # 15
print(keer5(keer3(2))) # 30
Uitvoer
27 15 30
Python's decorator-syntax vertrouwt zwaar op closures. Wanneer je een decorator schrijft, vangt de wrapper-functie de functie die het decoreert, wat een closure vormt.
Om een closure te inspecteren, gebruik het __closure__-attribuut. Het retourneert een tuple van cel-objecten die de ingeveselde waarden bevatten. Bijvoorbeeld:
>>> maak_vermenigvuldiger_van.__closure__
>>> keer3.__closure__
(<cell at 0x0000000002D155B8: int object at 0x000000001E39B6E0>,)
Elke cel's cell_contents-attribuut bevat de daadwerkelijke waarde die door de closure gevangen is:
>>> keer3.__closure__[0].cell_contents
3
>>> keer5.__closure__[0].cell_contents
5
Closures begrijpen geeft je de macht om schonere, modulairere Python-code te schrijven die onnodige globals vermijdt en functionele paradigma's omarmt.
Python
- Python Datatypes onder de knie krijgen: Een praktische gids
- Python Operators onder de knie krijgen: Een uitgebreide gids
- Python Pass Statement onder de knie krijgen: Een praktische gids
- Python Lambda Functies: Een praktische gids voor anonieme functies
- Python-dictionaries beheersen: aanmaken, manipuleren en geavanceerde technieken
- Python-generators: efficiënte iteratie en geavanceerde use cases
- Python-decorators beheersen: functies verbeteren met expert-technieken
- Python's strip()-methode beheersen: Uitgebreide handleiding & praktische voorbeelden
- Python lambda-functies beheersen: praktische voorbeelden & best practices
- Python abs()-functie: absolute waarden berekenen voor getallen & complexe getallen
- Python round()-functie uitgelegd met praktische voorbeelden