De term "closure" is ontleend aan functioneel programmeren en is vanaf het begin in Python aanwezig. Closures stellen een functie in staat om de omgeving waarin ze zijn gemaakt te onthouden, zelfs als ze buiten die omgeving worden aangeroepen. Dit concept biedt flexibiliteit en maakt de implementatie van veel patronen mogelijk, waaronder functie-fabrieken en lui berekeningen.
In Python zijn functies first-class objecten. Soms is het nodig dat een geneste functie variabelen uit de scope van de omvattende functie gebruikt, zelfs nadat deze is beëindigd. De gewone lexicale scope garandeert dit niet bij de terugkeer van de functie. Wanneer zo'n functie verwijst naar de omgevingsvariabelen van zijn creatie, ontstaat er een closure.
Een closure ontstaat wanneer de binnenste functie verwijst naar variabelen die in de buitenste functie zijn gedefinieerd, en die buitenste functie de binnenste functie teruggeeft. Dit wordt vaak gebruikt om functie-fabrieken te creëren, toestand te kapselen zonder klassen, en functies te construeren met parameters "on the spot".
def make_multiplier(factor): def multiplier(x): return x * factor return multiplier mul2 = make_multiplier(2) mul3 = make_multiplier(3) print(mul2(10)) # 20 print(mul3(10)) # 30
nonlocal gebruikt.Kan een closure veranderlijke toestand tussen aanroepen behouden als de variabele binnen de geneste functie wordt gewijzigd?
Ja, als je het sleutelwoord nonlocal in de geneste functie gebruikt. Zonder nonlocal creëert een toewijzing een nieuwe lokale variabele, zonder de buitenste te wijzigen.
def counter(): count = 0 def inc(): nonlocal count count += 1 return count return inc c = counter() print(c()) # 1 print(c()) # 2
Is het mogelijk om privé-variabelen in Python te implementeren met behulp van closures in plaats van klassen?
Ja, een closure biedt een eenvoudige implementatie van "privé" variabelen die niet van buitenaf toegankelijk zijn, tenzij getters/setters worden aangeboden in de geneste functie.
Worden closures alleen op functies toegepast? Kan een closure met lambda's in Python worden georganiseerd?
Ja, een closure kan ook worden gevormd met lambda-expressies, aangezien ze vergelijkbaar zijn met 'def' in hun binding van lexicale variabelen.
def make_power(n): return lambda x: x ** n square = make_power(2) cube = make_power(3) print(square(4)) # 16 print(cube(2)) # 8
nonlocal.Een functie-fabriek die handlers in een loop vormt, gebruikt de loopvariabele binnen de closure:
handlers = [] for i in range(3): def handler(x): return x + i handlers.append(handler) print([h(10) for h in handlers]) # [12, 12, 12]
Voordelen:
Nadelen:
i, de laatste waarde 2 — gedrag dat onvoorspelbaar is voor de meeste mensen.Een standaardargument is gebruikt om de waarde "vast te leggen":
handlers = [] for i in range(3): def handler(x, j=i): return x + j handlers.append(handler) print([h(10) for h in handlers]) # [10, 11, 12]
Voordelen:
Nadelen: