In Python ist ein Closure eine Funktion, die die Werte von äußeren Variablen "merkt", selbst wenn sie außerhalb ihres Sichtbarkeitsbereichs aufgerufen wird. Closures werden erstellt, wenn die innere Funktion auf Variablen verweist, die in der äußeren Funktion definiert sind. Um solche Variablen aus der eingebetteten Funktion in Python 3 zu ändern, wird das Schlüsselwort nonlocal verwendet.
Beispiel:
def make_accumulator(): total = 0 def add(value): nonlocal total total += value return total return add acc = make_accumulator() print(acc(10)) # 10 print(acc(5)) # 15
Ohne nonlocal wäre die Variable total nicht veränderbar (UnboundLocalError-Fehler).
Frage: "Kann man innerhalb einer eingebetteten Funktion die Variable der äußeren Funktion ohne das Schlüsselwort nonlocal erhöhen?"
Antwort: Nein, ohne nonlocal führt dies zu einem Fehler, da der Interpreter die Variable als lokal für die innere Funktion betrachtet. Beispiel:
def outer(): count = 0 def inner(): count += 1 # Fehler UnboundLocalError return count return inner
Geschichte In einer Webanwendung wollte man einen Zähler lokal für jeden Handler durch eingebettete Funktionen implementieren, vergaß jedoch das
nonlocal. Der Zähler gab immer 1 zurück, da er count im lokalen Bereich zählte und einen neuen, nicht mit dem äußeren Closure verbundenen, erhöhte.
Geschichte In Aufgaben zur Parallelisierung (Multithreading) werden oft Closures und Lambdas verwendet. Ohne Verständnis für Closures entstand eine Situation, in der alle Lambda-Funktionen den letzten Wert der Schleifenvariable "merkten", und die Aufgaben einander kopierten, anstatt verschiedene Aufgaben zu verarbeiten.
Geschichte Beim Schreiben eines Dekorators ohne Verwendung des richtigen Closures (keine Parameterübergabe an den äußeren Scope) entstand eine Situation, in der der Dekorator den Zustand zwischen den Aufrufen nicht speichern konnte, was zu unerwarteten Ergebnissen und instabiler Funktionsweise der Anwendung führte.