ProgrammierungPython-Entwickler

Was ist die 'LEGB-Regel' in Python? Wie funktioniert sie bei der Variablenbenennungssuche? Nennen Sie Beispiele für Situationen, in denen ein falsches Verständnis dieser Regel zu nicht trivialen Bugs führt.

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

Antwort.

LEGB-Regel – das ist die Regel zur Namensraumsuche (scoping) in Python. Die Abkürzung steht für:

  • Local – lokaler Namensraum (innerhalb einer Funktion);
  • Enclosing – Namensräume aller verschachtelten Funktionen;
  • Global – Modulraum (globale Variablen);
  • Builtin – eingebaute Namen in Python (len, list usw.).

Wenn Python auf eine Variable trifft, sucht es zuerst lokal, dann in verschachtelten Funktionen, dann im globalen Modulbereich und schließlich im Namensraum der eingebauten Objekte:

def outer(): x = 'enclosing' def inner(): x = 'local' print(x) inner() outer() # 'local'

Wenn innerhalb von inner() die Zuweisung x weggenommen wird, nimmt Python x aus dem enclosing scope (outer). Wenn dort auch keine Variable vorhanden ist, wird global gesucht, und danach in den eingebauten.


Fangfrage.

Wie ändert sich das Verhalten der Funktion, wenn Sie vergessen, nonlocal oder global zu deklarieren, wenn Sie eine Variable der äußeren Ebene ändern?

Antwort: Wenn man versucht, eine Variable des äußeren Scopes innerhalb einer verschachtelten Funktion ohne die Erklärung von nonlocal (oder global, falls die Variable im Modul ist) zu ändern, erstellt Python eine neue lokale Variable, ohne die äußere zu ändern.

Beispiel:

x = 10 def foo(): x = 20 # Das ist ein neues lokales x, global wird nicht geändert foo() print(x) # 10

Um globales x zu ändern:

def foo(): global x x = 20

Bei Variablen in der äußeren Funktion – verwenden Sie nonlocal.


Beispiele richtiger Fehler aufgrund mangelnden Verständnisses des Themas.


Geschichte 1

In einem Bildungsprojekt wurden verschachtelte Funktionen zur Zählung der Aufrufe verwendet. Der Entwickler schrieb:

def counter(): count = 0 def inc(): count += 1 return count return inc

Aber es trat ein UnboundLocalError auf, weil count innerhalb von inc() als neu betrachtet wurde (ein lokales count wurde erstellt). Lösung: count als nonlocal deklarieren.


Geschichte 2

In einer Webanwendung wollte man im Handler den global definierten Cache modifizieren:

cache = {} def add_to_cache(key, value): cache[key] = value

Wenn man jedoch innerhalb der Funktion versucht hätte, cache vollständig neu zu beschreiben, z.B. cache = {key: value}, hätte das einen neuen lokalen cache erstellt, der nicht mit dem globalen verbunden ist, da global cache fehlte.


Geschichte 3

In einem großen ETL-System trat ein Bug auf: Die Programmierer hatten die Variable result ohne eine explizite Initialisierung innerhalb der Funktion gelassen und erwarteten, dass sie aus dem äußeren Scope kommt. Aber nach mehreren Iterationen begann das Ergebnis durcheinander zu geraten, da innerhalb der Funktion result += value anstelle von result = result + value (ohne nonlocal/global) verwendet wurde – und result wurde bei jedem Aufruf neu initialisiert.