Frage

Was genau sind die Python Scoping-Regeln?

Wenn ich habe einige Code:

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

Wo ist x gefunden? Einige mögliche Optionen sind in der Liste unten:

  1. In der einschließenden Quelldatei
  2. In der Klasse Namespace
  3. In der Definition der Funktion
  4. In der for-Schleife Indexvariable
  5. Innerhalb der for-Schleife

Auch gibt es den Kontext während der Ausführung, wenn die Funktion spam woanders übergeben wird. Und vielleicht Lambda-Funktionen ein bisschen anders passieren?

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

War es hilfreich?

Lösung

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

LEGB Regel.

L , Lokale -. Namen in irgendeiner Weise innerhalb einer Funktion zugeordnet (def oder lambda)) und nicht in dieser Funktion global deklariert

E , Enclosing-Funktion Einheimischen - an. Name im lokalen Bereich von irgendwelchen und allen statisch umgebenden Funktionen (def oder lambda), von innen nach außen

G , Global (Modul) -. Name auf der obersten Ebene einer Moduldatei zugeordnet ist, oder durch eine global-Anweisung in einem def innerhalb der Datei ausführen

B , Built-in (Python) - Namen vorbelegt in dem eingebauten Namen Modul: open, range, SyntaxError, ...

Also, im Fall von

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

Der for-Schleife nicht über seinen eigenen Namensraum. In LEGB Reihenfolge würden die Bereiche

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

E: Geschlossene Funktion, alle einschließenden Funktionen (wenn das gesamte Beispiel in einer anderen def war)

G: Global. Gab es x erklärt global in dem Modul (code1)?

. B: Alle builtin x in Python

x wird nie in code2 (auch in den Fällen zu finden, wo man erwarten könnte wäre es, Antti Antwort oder sehen < a href = "https://stackoverflow.com/q/13905741/2810305"> hier ).

Andere Tipps

Im Wesentlichen das einzige, was in Python, die einen neuen Bereich einführt, ist eine Funktionsdefinition. Die Klassen sind ein bisschen ein Sonderfall, dass alles direkt im Körper definiert in der Klasse des Namensraum platziert ist, aber sie sind nicht direkt von innerhalb der Methoden (oder verschachtelte Klassen) sie enthalten.

In Ihrem Beispiel gibt es nur drei Bereiche, wo x in durchsucht wird:

  • Spam Anwendungsbereich - mit allem, was definiert in code3 und code5 (sowie code4, Ihre Schleifenvariable)

  • Die globale Reichweite - mit allem, was in code1 definiert, sowie Foo (und unabhängig von Änderungen, nachdem es)

  • Der builtins Namespace. Ein Bit eines speziellen Fall - dieses enthält die verschiedenen Funktionen und Python gebautet Typen wie len () und str (). Im Allgemeinen soll dies nicht von jedem Benutzer-Code geändert werden, so erwartet, dass es die Standardfunktionen und nichts anderes enthalten.

Weitere Bereiche werden nur angezeigt, wenn Sie eine verschachtelte Funktion (oder Lambda) in das Bild einzuführen. Diese werden so ziemlich verhalten, wie man es erwarten würde jedoch. Die verschachtelte Funktion kann alles im lokalen Bereich zugreifen, sowie alles in der Anwendungsbereich der einschließenden Funktion. zB.

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

Einschränkungen:

Variablen in Bereichen anders als die Variablen der lokalen Funktion zugegriffen werden kann, kann aber nicht auf neue Parameter ohne weitere Syntax Rebound werden. Stattdessen wird schaffen Zuordnung ein neues lokales Variable statt die Variable im übergeordneten Bereich zu beeinflussen. Zum Beispiel:

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 von den Bindungen der globalen Variablen, um tatsächlich zu ändern in einem Funktionsumfang, müssen Sie angeben, dass der Variable mit dem Schlüsselwort global global ist. Zum Beispiel:

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

Zur Zeit gibt es keine Möglichkeit, das gleiche gilt für Variablen in umschließenden zu tun Funktion Bereiche, aber Python 3 stellt ein neues Stichwort „nonlocal“, die in ähnlicher Weise wie global agieren, aber für verschachtelte Funktionsumfang.

Es gab keine ausführliche Antwort bezüglich Python3 Zeit, so dass ich eine Antwort hier.

Wie in anderen Antworten zur Verfügung gestellt, gibt es 4 grundlegende Bereiche, die LEGB, für lokale, Enclosing, Globale und Builtin. Zusätzlich zu diesen ist es eine besondere Tragweite, die Klasse Körper , die nicht eine umschließende Rahmen für Methoden innerhalb der Klasse definiert nicht umfasst; alle Zuordnungen innerhalb der Klasse Körper von dort die Variable machen auf in der Klasse Körper gebunden werden.

Insbesondere nicht Blockanweisung, neben def und class, einen variablen Bereich erstellen. In Python 2 eine Liste Verständnis schafft keinen Variable Umfang jedoch in Python 3 die Schleifenvariablen innerhalb Listenkomprehensionen in einem neuen Bereich erstellt werden.

Um die Besonderheiten der Klasse Körper zeigen

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 also in Funktion Körpern, können Sie die Variable auf den gleichen Namen in der Klasse Körper zuweisen können, eine Klassenvariable mit dem gleichen Namen zu erhalten; weitere Lookups auf diesem Namen resolve die Klasse Variable statt.


Einer der größeren Überraschungen zu viele Neulinge in Python ist, dass eine for Schleife keine Variable Umfang schafft. In Python 2 die Liste Comprehensions erstellen keinen Spielraum entweder Statt sie den Wert in der Funktion oder den globalen Bereich auslaufen (während Generatoren und dict Comprehensions tun!):

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

Die Comprehensions können als listig verwendet werden (oder schrecklich, wenn man so will) Art und Weise modifizierbar Variablen innerhalb Lambda-Ausdrücke in Python 2 - ein Lambda-Ausdruck hat einen variablen Bereich erstellen, wie die def Aussage würde, aber innerhalb von Lambda keine Aussagen sind erlaubt. Zuordnung eine Anweisung in Python zu sein bedeutet, dass keine Variablenzuweisungen in Lambda sind erlaubt, aber eine Liste Verständnis ist ein Ausdruck ...

Dieses Verhalten in Python 3 behoben wurde -. Keine Verständnis Ausdrücke oder Generatoren Variablen Leck


Die globale wirklich bedeutet, das Modul Umfang; das Haupt Python-Modul ist die __main__; alle importierten Module sind über die sys.modules variabel; zu erhalten Zugang zu einer __main__ sys.modules['__main__'] verwenden oder import __main__; Es ist durchaus akzeptabel Attribute gibt den Zugriff auf und ordnen; sie werden als Variablen im globalen Bereich des Hauptmoduls angezeigt.


Wenn ein Name überhaupt in dem aktuellen Bereich zugeordnet ist (außer im Klassenbereich), wird es in diesem Rahmen gehörte, in Betracht gezogen werden, sonst wird es zu gehören, einen umschließenden Umfang berücksichtigt werden, die auf die Variable zuweist (es könnte noch nicht zugeordnet werden, oder überhaupt nicht), oder schließlich die globale Reichweite. Wenn die Variable lokal betrachtet, aber es ist noch nicht gesetzt oder gelöscht wurde, wird zur Folge haben, den Variablenwert lesen in UnboundLocalError, die eine Unterklasse von NameError ist.

x = 5
def foobar():
    print(x)  # causes UnboundLocalError!
    x += 1    # because assignment here makes x a local variable within the function

# call the function
foobar()

kann der Umfang erklärt, dass er ausdrücklich den globalen (Modul scope) Variable mit dem Schlüsselwort global ändern will:

x = 5
def foobar():
    global x
    print(x)
    x += 1

foobar() # -> 5
print(x) # -> 6

Dies ist auch dann möglich, wenn es in umschließenden Umfang 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()      # -> 5 911
print(x, y) # -> 6 13

In Python 2 gibt es keine einfache Möglichkeit, den Wert in dem umschließenden Umfang zu modifizieren; in der Regel wird dies simuliert, indem einen veränderbaren Wert, wie zum Beispiel einer 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

Jedoch in Python 3, der nonlocal kommt die Rettung:

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 angenommen wird den aktuellen Bereich als lokal zu, oder jeden umschließenden Umfang, ist eine globale Variable. Ein globaler Name wird im Modul globalen Wörterbuch nachgeschlagen; wenn nicht gefunden wird, wird die globale sah dann aus dem builtins Modul nach oben; der Name des Moduls wurde aus Python 2 bis Python 3 geändert wird; in 2 Python war es __builtin__ und in Python 3 wird nun builtins genannt. Wenn Sie auf ein Attribut builtins Modul zuweisen, wird es danach zu jedem Modul als readabl sichtbar seine globaler Variable, es sei denn, dass das Modul sie mit ihren eigenen globalen Variablen mit dem gleichen Namen Schatten.


Das Lesen des eingebauten Modul kann auch nützlich sein; nehme an, dass Sie die Python 3 Artdruck Funktion in einigen Teilen der Datei, aber auch andere Teile der Datei verwenden, um die print Aussage noch wollen. In Python 2,6-2,7 können Sie halten, die Python 3 print Funktion erhalten mit:

import __builtin__

print3 = __builtin__.__dict__['print']

Die from __future__ import print_function nicht importieren eigentlich nicht die print Funktion überall in Python 2 - stattdessen die Funktion deaktiviert nur die Parsing-Regeln für print Anweisung im aktuellen Modul, print wie jeder andere Variablenbezeichner Handhabung und damit die print so dass die Funktion nachgeschlagen wird in dem builtins.

Die Scoping-Regeln für Python 2.x haben in anderen Antworten skizziert bereits. Das einzige, was ich möchte hinzufügen, dass in Python 3.0, gibt es auch das Konzept einer nicht-lokalen Bereich ist (durch die ‚nicht-lokalen‘ Keyword angegeben). Auf diese Weise können Sie direkt äußere Bereiche zugreifen zu können, und die Fähigkeit, eröffnet einige nette Tricks, einschließlich lexikalische Verschlüsse (ohne hässliche Hacks denen veränderbare Objekte).

EDIT:. Hier ist der PEP mit mehr Informationen zu diesem Thema

Ein etwas umfassenderes Beispiel für -umfang:

from __future__ import print_function  # for python 2 support

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)

    def method(self):
        print("4. Enclosed self.x", self.x)
        print("5. Global x", x)
        try:
            print(y)
        except NameError as e:
            print("6.", e)

    def method_local_ref(self):
        try:
            print(x)
        except UnboundLocalError as e:
            print("7.", e)
        x = 200 # causing 7 because has same name
        print("8. Local x", x)

inst = Test()
inst.method()
inst.method_local_ref()

Ausgabe:

1. Global x: 100
2. Enclosed y: 100
3. Enclosed x: 101
4. Enclosed self.x 101
5. Global x 100
6. global name 'y' is not defined
7. local variable 'x' referenced before assignment
8. Local x 200

Python löst Ihre Variablen mit - in der Regel - drei Namensräume zur Verfügung.

  

Sie können jederzeit während der Ausführung gibt   dessen mindestens drei Verschachtelungsebenen   Namensräume sind direkt zugänglich:   der innerste Umfang, die gesucht wird,   Erstens enthält die lokalen Namen; das   Namensräume aller umgebenden Funktionen,   die gesucht, beginnend mit der   nächster einschließenden Rahmen; die Mitte   Umfang, gesucht nächstes enthält die   aktuelle Moduls globaler Name; und das   äußerster Umfang (gesucht liest) ist die   Namensraum eingebauten Namen enthält.

Es gibt zwei Funktionen: globals und locals, die zeigen Sie den Inhalt zwei dieser Namensräume

.

Namespaces werden durch Pakete, Module, Klassen, Objektbau und Funktionen erstellt. Es gibt keine andere Aromen von Namensräumen.

In diesem Fall wird der Aufruf einer Funktion namens x hat in dem lokalen Namensraum oder dem globalen Namensraum aufgelöst werden.

Lokale in diesem Fall ist der Körper der Methode Funktion Foo.spam.

Global ist - na ja - global.

Die Regel ist die verschachtelten lokalen Räume erstellt von Methodenfunktionen (und verschachtelten Funktionsdefinitionen), dann suchen global zu suchen. Das ist es.

Es gibt keine anderen Bereiche. Die for Aussage (und andere zusammengesetzte Aussagen wie if und try) schaffen keine neue verschachtelte Bereiche. Nur Definitionen (Pakete, Module, Funktionen, Klassen und Objektinstanzen.)

Innerhalb einer Klassendefinition sind die Namen Teil der Klasse Namespace. code2 zum Beispiel müssen von den Klassennamen qualifiziert werden. Im Allgemeinen Foo.code2. Allerdings self.code2 wird auch funktionieren, weil Python-Objekte in der enthaltenden Klasse als Rückfall aussehen.

Ein Objekt (eine Instanz einer Klasse) hat Instanzvariablen. Diese Namen sind in der Objektnamespace. Sie müssen vom Objekt qualifiziert werden. (variable.instance.)

Von innerhalb einer Klassenmethode haben Sie Einheimische und Globals. Sie sagen self.variable die Instanz als den Namensraum zu holen. Sie werden bemerken, dass self ein Argument für jede Klasse Member-Funktion, es ist Teil des lokalen Namensraum zu machen.

Siehe Python Scope-Regeln , Python Scope , Variable Scope .

  

Wo ist x gefunden?

x wird nicht gefunden, wie man es nicht definiert haben. :-) Es könnte in code1 (global) oder code3 (local) gefunden werden, wenn Sie ihn dort.

code2 (Klasse Mitglieder) sind nicht sichtbar im Inneren Methode der gleichen Klasse zu codieren - Sie in der Regel, sie selbst mit Zugang würden. code4 / code5 (Loops) leben im selben Umfang wie code3, also wenn du da drin zu x geschrieben würden Sie die x-Instanz in code3 definiert werden zu ändern, nicht ein neues x zu machen.

Python ist statisch scoped, also wenn Sie ‚Spam‘ an eine andere Funktion Spam passieren müssen immer noch Zugriff auf Globals im Modul kam es aus (in code1 definiert ist) und alle anderen enthält Bereiche (siehe unten). code2 Mitglieder würden wieder durch Selbst zugegriffen werden.

Lambda ist nicht anders zu def. Wenn Sie eine Lambda in einer Funktion verwendet haben, ist es das gleiche wie eine verschachtelte Funktion definieren. In Python 2.2 an sind verschachtelte Bereiche zur Verfügung. In diesem Fall, dass Sie x auf jeder Ebene der Funktion Verschachtelung binden können und Python wird die innerste Instanz aufheben:

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 vom nächsten enthaltenden Bereich, die der Funktionsumfang mit fun2 zugeordnet ist. Aber auch die anderen x-Instanzen, definiert in fun1 und global, sind nicht betroffen.

Vor nested_scopes - in Python pre-2.1 und 2.1, wenn Sie speziell für das Feature fragen, mit einem von-future-Import - fun1 und fun2 die Bereiche zu fun3 nicht sichtbar sind, so S.Lott Antwort hält und Sie erhalten würden die globale x:

0 0

In Python

  

irgendeine Variable, die einen Wert zugeordnet ist, lokal zu dem Block, in dem   die Zuordnung angezeigt wird.

Wenn eine Variable nicht in dem aktuellen Bereich gefunden werden kann, entnehmen Sie bitte die LEGB Ordnung.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top