Python-sluitingen
Python-sluitingen
In deze zelfstudie leert u over Python-afsluiting, hoe u een afsluiting definieert en waarom u deze moet gebruiken.
Niet-lokale variabele in een geneste functie
Voordat we ingaan op wat een afsluiting is, moeten we eerst begrijpen wat een geneste functie en niet-lokale variabele is.
Een functie die binnen een andere functie is gedefinieerd, wordt een geneste functie genoemd. Geneste functies hebben toegang tot variabelen van het omsluitende bereik.
In Python zijn deze niet-lokale variabelen standaard alleen-lezen en we moeten ze expliciet als niet-lokaal declareren (met behulp van een niet-lokaal sleutelwoord) om ze te kunnen wijzigen.
Hieronder volgt een voorbeeld van een geneste functie die toegang heeft tot een niet-lokale variabele.
def print_msg(msg):
# This is the outer enclosing function
def printer():
# This is the nested function
print(msg)
printer()
# We execute the function
# Output: Hello
print_msg("Hello")
Uitvoer
Hello
We kunnen zien dat de geneste printer()
functie had toegang tot het niet-lokale bericht variabele van de omsluitende functie.
Een sluitingsfunctie definiëren
Wat zou er in het bovenstaande voorbeeld gebeuren als de laatste regel van de functie print_msg()
retourneerde de printer()
functie in plaats van het aan te roepen? Dit betekent dat de functie als volgt is gedefinieerd:
def print_msg(msg):
# This is the outer enclosing function
def printer():
# This is the nested function
print(msg)
return printer # returns the nested function
# Now let's try calling this function.
# Output: Hello
another = print_msg("Hello")
another()
Uitvoer
Hello
Dat is ongebruikelijk.
De print_msg()
functie is aangeroepen met de string "Hello"
en de geretourneerde functie was gebonden aan de naam another . Bij het bellen naar another()
, werd het bericht nog steeds onthouden, hoewel we al klaar waren met het uitvoeren van de print_msg()
functie.
Deze techniek waarmee sommige gegevens ("Hello
in dit geval) wordt gekoppeld aan de code heet afsluiting in Python .
Deze waarde in het omsluitende bereik wordt onthouden, zelfs wanneer de variabele buiten het bereik gaat of de functie zelf uit de huidige naamruimte wordt verwijderd.
Probeer het volgende in de Python-shell uit te voeren om de uitvoer te zien.
>>> del print_msg
>>> another()
Hello
>>> print_msg("Hello")
Traceback (most recent call last):
...
NameError: name 'print_msg' is not defined
Hier werkt de geretourneerde functie nog steeds, zelfs als de oorspronkelijke functie is verwijderd.
Wanneer zijn we gesloten?
Zoals te zien is in het bovenstaande voorbeeld, hebben we een sluiting in Python wanneer een geneste functie verwijst naar een waarde in het omsluitende bereik.
De criteria waaraan moet worden voldaan om afsluiting in Python te creëren, worden in de volgende punten samengevat.
- We moeten een geneste functie hebben (functie binnen een functie).
- De geneste functie moet verwijzen naar een waarde die is gedefinieerd in de omsluitende functie.
- De omsluitende functie moet de geneste functie teruggeven.
Wanneer gebruik je sluitingen?
Dus waar zijn sluitingen goed voor?
Sluitingen kunnen het gebruik van globale waarden vermijden en zorgen voor een vorm van gegevensverberging. Het kan ook een objectgeoriënteerde oplossing voor het probleem bieden.
Wanneer er weinig methoden (in de meeste gevallen één methode) in een klasse moeten worden geïmplementeerd, kunnen sluitingen een alternatieve en elegantere oplossing bieden. Maar wanneer het aantal attributen en methoden groter wordt, is het beter om een klasse te implementeren.
Hier is een eenvoudig voorbeeld waarbij een sluiting misschien meer de voorkeur heeft dan het definiëren van een klasse en het maken van objecten. Maar de voorkeur is helemaal aan jou.
def make_multiplier_of(n):
def multiplier(x):
return x * n
return multiplier
# Multiplier of 3
times3 = make_multiplier_of(3)
# Multiplier of 5
times5 = make_multiplier_of(5)
# Output: 27
print(times3(9))
# Output: 15
print(times5(3))
# Output: 30
print(times5(times3(2)))
Uitvoer
27 15 30
Python-decorateurs maken ook uitgebreid gebruik van sluitingen.
Tot slot is het goed om erop te wijzen dat de waarden die in de sluitingsfunctie worden ingesloten, kunnen worden achterhaald.
Alle functie-objecten hebben een __closure__
attribuut dat een tuple van celobjecten retourneert als het een sluitingsfunctie is. Verwijzend naar het bovenstaande voorbeeld, weten we times3
en times5
zijn sluitingsfuncties.
>>> make_multiplier_of.__closure__
>>> times3.__closure__
(<cell at 0x0000000002D155B8: int object at 0x000000001E39B6E0>,)
Het celobject heeft het attribuut cell_contents waarin de gesloten waarde wordt opgeslagen.
>>> times3.__closure__[0].cell_contents
3
>>> times5.__closure__[0].cell_contents
5
Python
- Python-gegevenstypen
- Python-operators
- Python pass-instructie
- Python Anonieme/Lambda-functie
- Python-woordenboek
- Python-generatoren
- Python-decorateurs
- Python String strip() Functie met VOORBEELD
- Python Lambda-functies met VOORBEELDEN
- Python abs() Functie:Voorbeelden van absolute waarden
- Python round() functie met VOORBEELDEN