ProgrammierungPython-Entwickler

Wie funktionieren Closures in Python? Was sind die Besonderheiten im Zugriff auf die Variablen der äußeren Funktion, und wie kann man Fallen im Zusammenhang mit der Änderbarkeit von Variablen vermeiden?

Bestehen Sie Vorstellungsgespräche mit dem Hintsage-KI-Assistenten

Antwort.

Closures sind ein mächtiger Mechanismus in Python, der es ermöglicht, Funktionen mit "gespeicherten" Daten aus dem umgebenden Kontext zu erstellen.

Hintergrund der Frage

In funktionalen Programmiersprachen und in Python sind Funktionen erstklassige Objekte. Eine Funktion kann eine neue Funktion zurückgeben, die Variablen aus ihrem umgebenden (äußeren) Geltungsbereich "schließt".

Problem

Entwickler sind oft verwirrt darüber, wie genau geschlossene Variablen innerhalb eines Closures "leben", wenn sie gelesen oder geschrieben werden, und wie man sicher mit ihnen umgeht (insbesondere mit veränderbaren Objekten).

Lösung

Wenn eine innere Funktion Variablen der äußeren Funktion verwendet, werden diese automatisch "gemerkt" — selbst wenn die äußere Funktion bereits abgeschlossen ist. Das Lesen einer Variablen ist offensichtlich, aber wenn man den Wert ändern möchte, muss das Schlüsselwort nonlocal verwendet werden. Bei der Arbeit mit veränderbaren Objekten (Listen, Dictionaries) ist dies ein besonderer Risikobereich.

Beispiel:

def outer(): count = 0 def inner(): nonlocal count count += 1 return count return inner counter = outer() print(counter()) # 1 print(counter()) # 2

Wichtige Merkmale:

  • Die innere Funktion merkt sich die Werte der Variablen, die zum Zeitpunkt ihrer Erstellung im Geltungsbereich vorhanden waren.
  • Um geschlossene Variablen zu ändern, verwenden Sie nonlocal (ansonsten wird eine lokale Variable erstellt).
  • Referenzen auf Objekte im Closure bleiben auch nach dem Verlassen der äußeren Funktion erhalten, was es ermöglicht, Funktionsfabriken, lexikalische Zähler und vieles mehr zu implementieren.

Fragen mit Hintergedanken.

Kann man den Wert einer geschlossenen Variablen innerhalb einer Funktion ohne nonlocal ändern?

Nein. Wenn Sie versuchen, einen neuen Wert zuzuweisen, ohne nonlocal anzugeben, betrachtet Python dies als Erstellung einer neuen lokalen Variablen, und der alte Wert wird nicht nach außen gehen.

Beispiel:

def make_counter(): count = 0 def inner(): count += 1 # Fehler UnboundLocalError! return count return inner

Kann man Argumente durch ein Closure in den äußeren Scope übergeben?

Ja, Closures "merken" sich alle Variablen, die im äußeren Geltungsbereich verfügbar sind, einschließlich Klassenattributen, globalen Variablen usw. Das Ändern dieser Variablen erfordert jedoch besonderen Aufwand (z. B. die Verwendung von nonlocal oder global).

Was passiert mit veränderbaren Objekten innerhalb eines Closures?

Wenn eine geschlossene Variable auf ein veränderbares Objekt verweist, z. B. eine Liste, können Sie seinen Inhalt ohne nonlocal ändern, aber wenn Sie versuchen, die Variable neu zuzuweisen, ist nonlocal erforderlich.

Beispiel:

def make_appender(): result = [] def append(x): result.append(x) # Ist erlaubt! return result return append f = make_appender() print(f(1)) # [1] print(f(2)) # [1, 2]

Typische Fehler und Anti-Patterns

  • Versuch, eine Variable im Closure ohne nonlocal neu zuzuweisen.
  • Verwendung von Closures zur Speicherung eines veränderbaren Zustands, ohne sich möglicher Gedächtnislecks bewusst zu sein.
  • Schwer lesbarer Code aufgrund einer zu großen Anzahl geschlossener Variablen.

Beispiel aus dem Leben

Negativer Fall

Ein Entwickler schreibt ein Closure, ändert eine Variable ohne nonlocal — es tritt ein UnboundLocalError auf.

Vorteile:

  • Schnelles Prototyping von Zählern, Fabriken.

Nachteile:

  • Unvorhersehbares Verhalten, Bugs bei Fehlern mit nonlocal.

Positiver Fall

Eindeutige Verwendung von nonlocal für einen kontrollierten Zustand in Closures.

Vorteile:

  • Deutlich kontrollierter Zustand, leicht umsetzbare Zähler und Funktionsfabriken.

Nachteile:

  • Schwieriger zu verstehen und zu debuggen große Ketten von Closures.