Kurze Beschreibung der Scoping Regeln?

Was genau sind die Python-Scoping-Regeln?

Wenn ich einen Code habe:

code1 class Foo: code2 def spam..... code3 for code4..: code5 x() 

Wo ist x gefunden? Einige mögliche Entscheidungen beinhalten die obige Liste:

  1. In der umschließenden Quelldatei
  2. Im Klassen-Namespace
  3. In der Funktionsdefinition
  4. In der for-Loop-Indexvariable
  5. Innerhalb der for-Schleife

Auch gibt es den Kontext während der Ausführung, wenn die Funktion Spam irgendwo anders passiert wird. Und vielleicht passieren Lambda-Funktionen etwas anders?

Es muss eine einfache Referenz oder ein Algorithmus irgendwo sein. Es ist eine verwirrende Welt für Python-Programmierer.

7 Solutions collect form web for “Kurze Beschreibung der Scoping Regeln?”

Eigentlich eine kurze Regel für Python Scope Auflösung, von Learning Python, 3.. Ed. . (Diese Regeln sind spezifisch für Variablennamen, nicht Attribute.Wenn Sie es ohne einen Zeitraum verweisen, gelten diese Regeln)

LEGB-Regel.

L , Lokale – Namen, die in einer beliebigen Weise innerhalb einer Funktion ( def oder lambda ) zugeordnet sind und in dieser Funktion nicht global deklariert sind.

E , Enclosing-Funktion Einheimische – Name im lokalen Bereich aller und alle statisch umschließenden Funktionen ( def oder lambda ), von innen nach außen.

G , Global (Modul) – Namen, die auf der obersten Ebene einer Moduldatei zugewiesen sind, oder indem sie eine global Anweisung in einem def innerhalb der Datei ausführen.

B , Built-in (Python) – Namen, die im eingebauten Namensmodul vorangestellt sind: open , range , SyntaxError , …

Also, im Falle von

 code1 class Foo: code2 def spam..... code3 for code4..: code5 x() 

Die for-Schleife hat keinen eigenen Namensraum. In der LEGB-Reihenfolge wären die Scopes

L: lokal, in def spam (in code3 , code 4 , code5 ).

E: Geschlossene Funktion, alle umschließenden Funktionen (wenn das ganze Beispiel in einem anderen def )

G: Globale Gibt es irgendwelche x global deklariert im Modul ( code1 )?

B: Jeder eingebaute x in Python.

x wird niemals in code2 (auch in Fällen, in denen du es erwarten code2 , siehe Anttis Antwort oder hier ).

Im Wesentlichen ist die einzige Sache in Python, die einen neuen Bereich einführt, eine Funktionsdefinition. Klassen sind ein bisschen ein besonderer Fall darin, dass irgendetwas, das direkt im Körper definiert ist, im Namensraum der Klasse platziert wird, aber sie sind nicht direkt von den Methoden (oder verschachtelten Klassen) zugänglich, die sie enthalten.

In deinem Beispiel gibt es nur 3 Bereiche, in denen x gesucht wird:

  • Spam-Bereich – mit allem, was in Code3 und Code5 definiert ist (sowie Code4, Ihre Loop-Variable)

  • Der globale Geltungsbereich – der alles enthält, was in Code1 definiert ist, sowie Foo (und was auch immer Änderungen danach)

  • Der Namensraum der eingebauten. Ein bisschen Spezialfall – das enthält die verschiedenen Python-Funktionen und Typen wie len () und str (). Im Allgemeinen sollte dies nicht durch einen Benutzercode geändert werden, also erwarten Sie, dass es die Standardfunktionen enthält und sonst nichts.

Mehr Scopes erscheinen nur, wenn Sie eine verschachtelte Funktion (oder Lambda) in das Bild einführen. Diese werden sich so gut verhalten, wie man es erwarten würde. Die verschachtelte Funktion kann auf alles im lokalen Bereich zugreifen, ebenso wie alles im Bereich der umschließenden Funktion. z.B.

 def foo(): x=4 def bar(): print x # Accesses x from foo's scope bar() # Prints 4 x=5 bar() # Prints 5 

Beschränkungen:

Variablen in anderen Bereichen als den Variablen der lokalen Funktion können aufgerufen werden, können aber ohne weitere Syntax nicht auf neue Parameter zurückgesetzt werden. Stattdessen wird die Zuweisung eine neue lokale Variable erstellen, anstatt die Variable im übergeordneten Bereich zu beeinflussen. Beispielsweise:

 global_var1 = [] global_var2 = 1 def func(): # This is OK: It's just accessing, not rebinding global_var1.append(4) # This won't affect global_var2. Instead it creates a new variable global_var2 = 2 local1 = 4 def embedded_func(): # Again, this doen't affect func's local1 variable. It creates a # new local variable also called local1 instead. local1 = 5 print local1 embedded_func() # Prints 5 print local1 # Prints 4 

Um die Bindungen von globalen Variablen innerhalb eines Funktionsumfangs tatsächlich zu ändern, müssen Sie angeben, dass die Variable global mit dem globalen Schlüsselwort ist. Z.B:

 global_var = 4 def change_global(): global global_var global_var = global_var + 1 

Derzeit gibt es keine Möglichkeit, dasselbe für Variablen in der Einbeziehung von Funktionsbereichen zu tun, aber Python 3 führt ein neues Keyword ein, " nonlocal ", das in ähnlicher Weise wie global agieren wird, aber für verschachtelte Funktionsbereiche.

Es gab keine gründliche Antwort auf Python3 Zeit, also habe ich hier eine Antwort gemacht.

Wie in anderen Antworten vorgesehen, gibt es 4 grundlegende Bereiche, die LEGB, für Local, Enclosing, Global und Builtin. Zusätzlich zu diesen gibt es einen besonderen Umfang, der Klassenkörper , der keinen umschließenden Bereich für in der Klasse definierte Methoden umfasst; Irgendwelche Zuordnungen innerhalb des Klassenkörpers machen die Variable von dort aus in der Klasse Körper gebunden werden.

Vor allem keine Block-Anweisung, neben def und class , erstellen Sie einen variablen Bereich. In Python 2 erzeugt das Listenverständnis keinen Variablenbereich, aber in Python 3 wird die Loop-Variable in einem neuen Bereich angelegt.

Um die Besonderheiten des Klassenkörpers zu demonstrieren

 x = 0 class X(object): y = x x = x + 1 # x is now a variable z = x def method(self): print(self.x) # -> 1 print(x) # -> 0, the global x print(y) # -> NameError: global name 'y' is not defined inst = X() print(inst.x, inst.y, inst.z, x) # -> (1, 0, 1, 0) 

Im Gegensatz zum Funktionskörper können Sie die Variable im Klassenkörper demselben Namen zuordnen, um eine Klassenvariable mit demselben Namen zu erhalten. Weitere Lookups auf diesem Namen lösen stattdessen die Klassenvariable.


Eine der größeren Überraschungen für viele Newcomer zu Python ist, dass eine for Schleife keinen variablen Bereich erzeugt. In Python 2 erstellen die Listenverständnisse auch keinen Bereich (während Generatoren und dict Verständnisse tun!) Stattdessen lecken sie den Wert in der Funktion oder dem globalen Geltungsbereich:

 >>> [ i for i in range(5) ] >>> i 4 

Das Verständnis kann als eine List (oder schrecklich, wenn Sie wollen), um modifizierbare Variablen innerhalb von Lambda-Ausdrücken in Python 2 zu machen – ein Lambda-Ausdruck erzeugt einen variablen Bereich, wie die def Anweisung, aber innerhalb von lambda keine Anweisungen erlaubt sind. Zuweisung, die eine Anweisung in Python ist, bedeutet, dass keine Variablenzuweisungen in Lambda erlaubt sind, aber ein Listenverständnis ist ein Ausdruck …

Dieses Verhalten wurde in Python 3 behoben – keine Verständnisausdrücke oder Generatoren Leckvariablen.


Die globale bedeutet wirklich den Modulumfang; Das __main__ ist das __main__ ; Alle importierten Module sind über die Variable sys.modules zugänglich; Um Zugang zu __main__ zu erhalten, kann man sys.modules['__main__'] oder import __main__ ; Es ist vollkommen akzeptabel, auf Attribute zuzugreifen und zuzuordnen; Sie werden als Variablen im globalen Umfang des Hauptmoduls angezeigt.


Wenn ein Name im aktuellen Geltungsbereich (außer im Klassenumfang) zugewiesen wird, wird er als zu diesem Geltungsbereich gehörig angesehen, andernfalls wird er davon ausgegangen, dass er zu einem umschließenden Bereich gehört, der der Variablen zugeordnet ist (er darf nicht zugewiesen werden Doch oder gar nicht) oder endlich der globale Geltungsbereich. Wenn die Variable als lokal betrachtet wird, aber noch nicht gesetzt oder gelöscht wurde, wird das Lesen des Variablenwertes zu UnboundLocalError , was eine Unterklasse von NameError .

 x = 5 def foobar() print(x) # UnboundLocalError! x += 1 # assignment here makes xa local variable! 

Der Geltungsbereich kann erklären, dass er explizit die globale Variable Variable (Modulumfang) mit dem globalen Schlüsselwort ändern möchte:

 x = 5 def foobar(): global x print(x) # -> 5 x += 1 foobar() print(x) # -> 6 

Dies ist auch möglich, auch wenn es im eingeschlossenen Bereich beschattet wurde:

 x = 5 y = 13 def make_closure(): x = 42 y = 911 def func(): global x # sees the global value print(x, y) x += 1 return func func = make_closure() func() # -> print 5 911 print(x, y) # -> 6 13 

In python 2 gibt es keine einfache Möglichkeit, den Wert im Umschließungsbereich zu ändern; In der Regel wird dies durch einen veränderlichen Wert simuliert, wie zB eine Liste mit einer Länge von 1:

 def make_closure(): value = [0] def get_next_value(): value[0] += 1 return value[0] return get_next_value get_next = make_closure() print(get_next()) # -> 1 print(get_next()) # -> 2 

Doch in python 3 kommt die nonlocal zu retten:

 def make_closure(): value = 0 def get_next_value(): nonlocal value value += 1 return value return get_next_value get_next = make_closure() # identical behavior to the previous example. 

Jede Variable, die nicht als lokal für den aktuellen Geltungsbereich oder einen beliebigen Umschließungsbereich gilt, ist eine globale Variable. Ein globaler Name wird im globalen Wörterbuch des Moduls nachgeschlagen. Wenn nicht gefunden, wird das Globale dann aus dem eingebauten Modul nachgeschlagen; Der Name des Moduls wurde von python 2 zu python 3 geändert; In python 2 es war __builtin__ und in python 3 es heißt jetzt builtins . Wenn Sie einem Attribut des eingebauten Moduls zuordnen, wird es danach jedem Modul als lesbare globale Variable sichtbar, es sei denn, dass das Modul sie mit einer eigenen globalen Variablen mit demselben Namen schattiert.


Das Lesen des eingebauten Moduls kann auch nützlich sein; Angenommen, Sie wollen die Python-3-Style-Druckfunktion in einigen Teilen der Datei, aber andere Teile der Datei verwenden immer noch die print , wenn Ihre Python-Version> = 2.6 ist, können Sie die neue Stilfunktion wie:

 import __builtin__ print3 = __builtin__.__dict__['print'] 

Die from __future__ import print_function eigentlich nicht die print irgendwo in Python 2 – stattdessen schaltet sie einfach die Parsing-Regeln für die print Anweisung im aktuellen Modul ab und verarbeitet den print wie jede andere Variablenkennung und ermöglicht so dem print die Funktion nachgeschlagen werden In den eingebauten.

Die Scoping-Regeln für Python 2.x wurden bereits in anderen Antworten skizziert. Das einzige, was ich hinzufügen würde, ist, dass in Python 3.0, gibt es auch das Konzept eines nicht-lokalen Bereich (angezeigt durch die "nonlocal" Schlüsselwort). So können Sie direkt auf äußere Bereiche zugreifen und eröffnen die Möglichkeit, einige nette Tricks zu machen, einschließlich lexikalischer Verschlüsse (ohne hässliche Hacks mit veränderlichen Objekten).

EDIT: Hier ist der PEP mit mehr Informationen dazu.

Ein etwas kompletteres Beispiel:

 x = 100 print "1. Global x:", x class Test(object): y = x print "2. Enclosed y:", y x = x + 1 print "3. Enclosed x:", x z = x def method(self): print "4. Enclosed self.x", self.x print "5. Global x", x try: print y except NameError, e: print "6.", e def method_local_ref(self): try: print x except UnboundLocalError, e: print "7.", e x = 200 print "8. Local x", x inst = Test() inst.method() inst.method_local_ref() 

Ausgabe:

  1. Global x: 100
  2. Geschlossen y: 100
  3. Geschlossen x: 101
  4. Geschlossenes self.x 101
  5. Global x 100
  6. Der globale Name 'y' ist nicht definiert
  7. Lokale Variable 'x' referenziert vor der Zuweisung
  8. Lokal x 200

Python löst deine Variablen mit – im Allgemeinen – drei Namespaces zur Verfügung.

Zu jeder Zeit während der Ausführung gibt es mindestens drei verschachtelte Bereiche, deren Namensräume direkt zugänglich sind: Der innerste Bereich, der zuerst gesucht wird, enthält die lokalen Namen; Die Namespaces aller umschließenden Funktionen, die mit dem nächstgelegenen Umfeld gesucht werden; Der mittlere Bereich, der als nächstes gesucht wird, enthält die globalen Namen des aktuellen Moduls. Und der äußerste Bereich (zuletzt gesucht) ist der Namespace mit eingebauten Namen.

Es gibt zwei Funktionen: globals und locals die Ihnen den Inhalt zwei dieser Namespaces zeigen.

Namensräume werden durch Pakete, Module, Klassen, Objektaufbau und Funktionen erstellt. Es gibt keine anderen Geschmacksrichtungen von Namespaces.

In diesem Fall muss der Aufruf einer Funktion namens x im lokalen Namensraum oder im globalen Namespace aufgelöst werden.

Lokal in diesem Fall ist der Körper der Methodenfunktion Foo.spam .

Global ist – gut – global.

Die Regel besteht darin, die verschachtelten lokalen Räume zu durchsuchen, die durch Methodenfunktionen (und verschachtelte Funktionsdefinitionen) erstellt wurden, und dann global suchen. Das ist es.

Es gibt keine anderen Bereiche. Die for Anweisung (und andere zusammengesetzte Anweisungen wie if und try ) erstellen keine neuen verschachtelten Bereiche. Nur Definitionen (Pakete, Module, Funktionen, Klassen und Objektinstanzen).

Innerhalb einer Klassendefinition sind die Namen Teil des Klassennamensraums. code2 muss zum Beispiel durch den Klassennamen qualifiziert sein. Im Allgemeinen Foo.code2 . Allerdings wird self.code2 auch funktionieren, da Python-Objekte die enthaltene Klasse als Rückfall ansehen.

Ein Objekt (eine Instanz einer Klasse) hat Instanzvariablen. Diese Namen befinden sich im Namensraum des Objekts. Sie müssen vom Objekt qualifiziert sein. ( variable.instance .)

Innerhalb einer Klassenmethode haben Sie Einheimische und Globals. Sie sagen, self.variable , um die Instanz als Namespace zu wählen. Sie werden feststellen, dass self ein Argument für jede Klassenmitgliedsfunktion ist und es Teil des lokalen Namensraums ist.

Siehe Python Scope Rules , Python Scope , Variable Scope .

Wo ist x gefunden?

X ist nicht gefunden, da du es nicht definiert hast. 🙂 Es könnte in Code1 (global) oder Code3 (lokal) gefunden werden, wenn man es dort hinlegt.

Code2 (Klassenmitglieder) sind nicht sichtbar, um innerhalb von Methoden der gleichen Klasse zu codieren – Sie würden normalerweise mit ihnen selbst zugreifen. Code4 / Code5 (Loops) live im selben Umfang wie Code3, also wenn du an x ​​geschrieben hast, dann würdest du die x-Instanz ändern, die in Code3 definiert ist und keine neue x macht.

Python ist statisch scoped, also, wenn Sie 'Spam' zu einer anderen Funktion Spam passieren wird immer noch Zugang zu globals in dem Modul kam es aus (definiert in Code1), und alle anderen mit Scopes (siehe unten). Code2 Mitglieder würden wieder durch Selbst zugänglich sein.

Lambda ist nicht anders als def. Wenn du ein Lambda benutzt hast, das in einer Funktion verwendet wird, ist es dasselbe wie das Definieren einer verschachtelten Funktion. In Python 2.2 stehen nun verschachtelte Bereiche zur Verfügung. In diesem Fall können Sie x auf jeder Ebene der Funktion Nesting binden und Python wird die innerste Instanz abholen:

 x= 0 def fun1(): x= 1 def fun2(): x= 2 def fun3(): return x return fun3() return fun2() print fun1(), x 2 0 

Fun3 sieht die Instanz x aus dem nächstgelegenen Bereich, der der Funktionsumfang mit fun2 ist. Aber die anderen x-Instanzen, die in fun1 und global definiert sind, sind nicht betroffen.

Vor nested_scopes – in Python pre-2.1 und in 2.1, wenn du nicht gezielt nach dem Feature mit einem from-future-import – fun1 und fun2's Scopes sind nicht sichtbar für fun3, so dass S.Lott's Antwort hält und man würde die globale x erhalten :

 0 0 
  • Python-Funktion Anrufe sind Blutungen Umfang, stateful, nicht zu initialisieren Parameter?
  • Globals und Einheimische in python exec ()
  • Funktion Ortsname Bindung aus einem äußeren Bereich
  • Warum verschachtelte Funktionen auf Variablen von äußeren Funktionen zugreifen können, aber sie nicht ändern dürfen [duplizieren]
  • Variable Bereiche in Python-Klassen
  • Warum ist eine Klassenvariable nicht im Listenverständnis definiert, sondern eine andere ist?
  • Warum erbt keine Unterfunktion den Bereich in Python?
  • Python - Wie man eine globale Variable aus einer Funktion
  • Python: Variablen sind noch zugänglich, wenn in try oder if definiert?
  • Python überschreibt Variablen in verschachtelten Funktionen
  • Scoping in Python 'für' Schleifen
  • Python ist die beste Programmiersprache der Welt.