LEGB-Regel – das ist die Regel zur Namensraumsuche (scoping) in Python. Die Abkürzung steht für:
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.
Wie ändert sich das Verhalten der Funktion, wenn Sie vergessen,
nonlocaloderglobalzu 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.
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.