Der Begriff "Closure" wurde aus der funktionalen Programmierung entlehnt und ist seit Beginn in Python vorhanden. Closures ermöglichen es einer Funktion, die Umgebung, in der sie erstellt wurde, zu speichern, selbst wenn sie außerhalb dieser Umgebung aufgerufen wird. Dieses Konzept bietet Flexibilität und ermöglicht die Implementierung vieler Muster, einschließlich Funktionsfabriken und fauler Berechnungen.
In Python sind Funktionen Objekte erster Klasse. Manchmal ist es notwendig, dass eine eingebettete Funktion auf Variablen aus dem Geltungsbereich der umschließenden Funktion zugreift, selbst nachdem diese abgeschlossen ist. Die normale lexikalische Geltung garantiert dies beim Rückgabe der Funktion nicht. Wenn eine solche Funktion auf die Variablen ihrer Umgebung zugreift, entsteht ein Closure.
Ein Closure entsteht, wenn die innere Funktion auf Variablen verweist, die in der äußeren definiert sind, und die äußere die innere nach außen zurückgibt. Dies wird häufig verwendet, um Funktionsfabriken zu erstellen, den Zustand ohne Klassen zu kapseln und eine Funktion mit "on-the-fly"-Parametern zu konstruieren.
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 verwendet.Kann ein Closure einen veränderbaren Zustand zwischen den Aufrufen beibehalten, wenn die Variable in der inneren Funktion geändert wird?
Ja, wenn in der inneren Funktion das Schlüsselwort nonlocal verwendet wird. Ohne nonlocal erstellt eine Zuweisung eine neue lokale Variable, ohne die äußere zu ändern.
def counter(): count = 0 def inc(): nonlocal count count += 1 return count return inc c = counter() print(c()) # 1 print(c()) # 2
Können private Variablen in Python mithilfe von Closures anstelle von Klassen implementiert werden?
Ja, Closures bieten eine einfache Implementierung "privater" Variablen, die von außen nicht zugänglich sind, es sei denn, Getter/Setter werden in der inneren Funktion bereitgestellt.
Gilt die Closure-Anwendung nur für Funktionen? Kann ein Closure auch mit Lambdas in Python organisiert werden?
Ja, ein Closure kann auch mit Lambda-Ausdrücken gebildet werden, da sie in Bezug auf die Bindung von lexikalischen Variablen analog zu def sind.
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.Eine Funktionsfabrik, die Handler in einer Schleife erstellt, verwendet die Schleifenvariable innerhalb des Closures:
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]
Vorteile:
Nachteile:
i, ihr letzter Wert ist 2 — das Verhalten ist für die meisten unerwartet.Ein Standardargument wurde verwendet, um den Wert "festzulegen":
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]
Vorteile:
Nachteile: