Code 1

x = 0

class Foo:
    print(x)
    x = 1
    print(x)

print(x)

Ergebnis 1

0
1
0

Code 2

x = 0

def foo():
    print(x)
    x = 1
    print(x)

foo()

Ergebnis 2

UnboundLocalError: local variable 'x' referenced before assignment.

Warum können x Objekte aus zwei Namespaces in class block referenzieren?
Ich verstehe nicht, warum Code 1 kein UnboundLocalError wirft.
Inkonsistenzen zwischen Funktion und Klasse stören mich.


Aktualisieren:

Nachdem ich die Python-Dokumente mehrmals gelesen habe, kann ich die Gültigkeitsbereichsregeln immer noch nicht verstehen.

Das Folgende sind Blöcke: ein Modul, ein Funktionskörper und eine Klassendefinition. ...[überspringen]...

Wenn ein Name in einem Block gebunden ist, ist er eine lokale Variable dieses Blocks, sofern er nicht als nicht lokal deklariert ist. Wenn ein Name auf Modulebene gebunden ist, handelt es sich um eine globale Variable. (Die Variablen des Modulcodeblocks sind lokal und global.) Wenn eine Variable in einem Codeblock verwendet, aber dort nicht definiert wird, handelt es sich um eine freie Variable.

Wenn eine Namensbindungsoperation irgendwo innerhalb eines Codeblocks auftritt, werden alle Verwendungen des Namens innerhalb des Blocks als Verweise auf den aktuellen Block behandelt. Dies kann zu Fehlern führen, wenn ein Name innerhalb eines Blocks verwendet wird, bevor er gebunden wird. Diese Regel ist subtil. In Python fehlen Deklarationen und es können Namensbindungsvorgänge an einer beliebigen Stelle innerhalb eines Codeblocks ausgeführt werden. Die lokalen Variablen eines Codeblocks können bestimmt werden, indem der gesamte Text des Blocks nach Namensbindungsoperationen durchsucht wird.

7
kev 10 Okt. 2012 im 04:45

3 Antworten

Beste Antwort
x = 0

class Foo:
    print(x)   # Foo.x isn't defined yet, so this is the global x
    x = 1      # This is referring to Foo.x
    print(x)   # So is this

print(x)

x = 0

def foo():
    print(x)   # Even though x is not defined yet, it's known to be local
               # because of the assignment
    x = 1      # This assignment means x is local for the whole function
    print(x)

foo()
6
John La Rooy 10 Okt. 2012 im 00:49

Der Klassenblock kennt keine "lokalen" Variablen, sondern nur Klassenvariablen. Sie unterscheiden sich von lokalen Variablen darin, dass sie nach der Ausführung des Blocks nicht vergessen werden. Sie bleiben als Felder in der Klasse. Lokale und Klassenvariablen werden in mehr als nur diesem Aspekt unterschiedlich behandelt, daher ist es nicht verwunderlich, dass kein ungebundener Fehler ausgelöst wird. Schließlich haben Sie keine undefinierte lokale Variable, die die globale Variable beschattet. Daher ist der Zugriff auf die globale Variable vor dem Definieren der Klassenvariablen kein Problem.

Vielleicht sollte der Compiler auch irgendwie davor warnen, aber derzeit nicht.

1
Alfe 10 Okt. 2012 im 00:52