Python-Schließungen
Python-Schließungen
In diesem Tutorial erfahren Sie mehr über die Schließung in Python, wie man eine Schließung definiert und warum man sie verwenden sollte.
Nichtlokale Variable in einer verschachtelten Funktion
Bevor wir uns damit befassen, was eine Closure ist, müssen wir zuerst verstehen, was eine verschachtelte Funktion und eine nichtlokale Variable sind.
Eine Funktion, die in einer anderen Funktion definiert ist, wird als verschachtelte Funktion bezeichnet. Verschachtelte Funktionen können auf Variablen des einschließenden Geltungsbereichs zugreifen.
In Python sind diese nicht-lokalen Variablen standardmäßig schreibgeschützt und wir müssen sie ausdrücklich als nicht-lokal deklarieren (mit dem Schlüsselwort nonlocal), um sie zu ändern.
Es folgt ein Beispiel einer verschachtelten Funktion, die auf eine nicht lokale Variable zugreift.
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")
Ausgabe
Hello
Wir können sehen, dass der verschachtelte printer()
-Funktion konnte auf die nicht lokale msg zugreifen Variable der einschließenden Funktion.
Definieren einer Abschlussfunktion
Was würde im obigen Beispiel passieren, wenn die letzte Zeile der Funktion print_msg()
gab den printer()
zurück Funktion anstatt sie aufzurufen? Das heißt, die Funktion wurde wie folgt definiert:
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()
Ausgabe
Hello
Das ist ungewöhnlich.
Die print_msg()
Funktion wurde mit dem String "Hello"
aufgerufen und die zurückgegebene Funktion wurde an den Namen another gebunden . Beim Aufruf von another()
, wurde die Nachricht noch gespeichert, obwohl wir die Ausführung von print_msg()
bereits beendet hatten Funktion.
Diese Technik, mit der einige Daten ("Hello
in diesem Fall) an den Code angehängt wird, heißt in Python closure .
Dieser Wert im einschließenden Geltungsbereich wird auch dann gespeichert, wenn die Variable den Geltungsbereich verlässt oder die Funktion selbst aus dem aktuellen Namensraum entfernt wird.
Versuchen Sie Folgendes in der Python-Shell auszuführen, um die Ausgabe anzuzeigen.
>>> del print_msg
>>> another()
Hello
>>> print_msg("Hello")
Traceback (most recent call last):
...
NameError: name 'print_msg' is not defined
Hier funktioniert die zurückgegebene Funktion auch dann noch, wenn die ursprüngliche Funktion gelöscht wurde.
Wann haben wir Schließungen?
Wie aus dem obigen Beispiel ersichtlich, haben wir in Python eine Closure, wenn eine verschachtelte Funktion auf einen Wert in ihrem einschließenden Gültigkeitsbereich verweist.
Die Kriterien, die erfüllt sein müssen, um Closure in Python zu erstellen, sind in den folgenden Punkten zusammengefasst.
- Wir müssen eine verschachtelte Funktion haben (Funktion innerhalb einer Funktion).
- Die verschachtelte Funktion muss auf einen Wert verweisen, der in der umschließenden Funktion definiert ist.
- Die einschließende Funktion muss die verschachtelte Funktion zurückgeben.
Wann werden Closures verwendet?
Wozu sind Verschlüsse also gut?
Closures können die Verwendung globaler Werte vermeiden und bieten eine Art Datenverbergung. Es kann auch eine objektorientierte Lösung für das Problem bereitstellen.
Wenn in einer Klasse nur wenige Methoden (in den meisten Fällen eine Methode) implementiert werden müssen, können Closures eine alternative und elegantere Lösung bieten. Aber wenn die Anzahl der Attribute und Methoden größer wird, ist es besser, eine Klasse zu implementieren.
Hier ist ein einfaches Beispiel, bei dem eine Closure besser sein könnte, als eine Klasse zu definieren und Objekte zu erstellen. Aber die Präferenz liegt ganz bei Ihnen.
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)))
Ausgabe
27 15 30
Auch Python-Dekoratoren machen ausgiebigen Gebrauch von Closures.
Abschließend sei darauf hingewiesen, dass die Werte, die in die Closure-Funktion eingeschlossen werden, herausgefunden werden können.
Alle Funktionsobjekte haben einen __closure__
-Attribut, das ein Tupel von Zellobjekten zurückgibt, wenn es sich um eine Abschlussfunktion handelt. Unter Bezugnahme auf das obige Beispiel kennen wir times3
und times5
sind Abschlussfunktionen.
>>> make_multiplier_of.__closure__
>>> times3.__closure__
(<cell at 0x0000000002D155B8: int object at 0x000000001E39B6E0>,)
Das cell-Objekt hat das Attribut cell_contents, das den geschlossenen Wert speichert.
>>> times3.__closure__[0].cell_contents
3
>>> times5.__closure__[0].cell_contents
5
Python