python noobie scoping Frage

8

Ich habe diesen Code geschrieben:

%Vor%

Versuche zu testen, ob Python ein lexikalischer oder dynamischer Bereich ist. Mein Denken war das

%Vor%

Sollte entweder 0 oder 1 ausgeben, und das würde mir sagen, wie Python im Visier ist. Beim Aufruf von y wird jedoch eine Ausnahme ausgelöst, die besagt, dass x nicht definiert ist. Mein Verständnis von Pythons Arbeitsweise scheint grundlegend fehlerhaft zu sein.

Kann jemand erklären, wie das funktioniert? Ja, mir ist bewusst, dass dies leicht mit Objekten möglich ist. Ich versuche, die Idee zu verstehen, Funktionen ohne den Gebrauch von Objekten zu geben. Ich habe den Code auf diese Weise geschrieben, weil das obige, das in eine lexikalisch begrenzte Sprache wie Scheme übersetzt wurde, definitiv funktioniert hätte.

    
amatsukawa 29.05.2011, 23:11
quelle

5 Antworten

10

Von den Dokumenten :

  

Eine besondere Eigenart von Python ist das - wenn   keine globale Aussage ist in Kraft -   Zuordnungen zu Namen gehen immer hinein   der innerste Bereich. Aufgaben tun   keine Daten kopieren - sie binden nur Namen   zu Objekten.

Also, wenn Python

analysiert %Vor%

sieht die Zuweisung x += 1 und entscheidet daher, dass x im innersten Bereich sein muss. Wenn Sie später temp(...) über y() - aufrufen (wobei übrigens self in der Definition von temp weggelassen werden sollte oder sonst y() ein Argument liefern soll) - trifft Python die print x -Anweisung und findet, dass x nicht im lokalen (innersten) Bereich definiert wurde. Daher der Fehler

%Vor%

Wenn Sie

deklarieren %Vor%

Dann sucht Python im globalen Bereich nach x (wo x=0 ). In Python2 gibt es keine Möglichkeit Python im erweiterten Bereich nach x zu suchen (wo x=1 ). Aber in Python3 kann das mit der Deklaration

erreicht werden %Vor%     
unutbu 29.05.2011 23:32
quelle
6

Python hat zwei Bereiche (was eigentlich drei ist) plus spezielle Regeln für verschachtelte lokale Bereiche. Die beiden Bereiche sind global für die Namen auf Modulebene und local für alles in einer Funktion. Alles, was Sie einer Funktion zuweisen, ist automatisch lokal, es sei denn, Sie deklarieren das Gegenteil mit der global -Anweisung in dieser Funktion . Wenn Sie einen Namen verwenden, der nirgendwo in der Funktion zugewiesen ist, handelt es sich nicht um einen lokalen Namen. Python sucht (lexikalisch) nach Verschachtelungsfunktionen, um zu sehen, ob sie diesen Namen als lokalen Namen haben. Wenn keine Verschachtelungsfunktionen vorhanden sind oder der Name in keinem von ihnen lokal ist, wird angenommen, dass der Name global ist.

(Der globale Namespace ist ebenfalls speziell, da er sowohl der globale Modulname als auch der eingebaute Namespace ist, der im Modul builtins oder __builtins__ versteckt ist.)

In Ihrem Fall haben Sie drei x -Variablen: eine im Modul (global), eine in der counter -Funktion und eine in der temp -Funktion - weil += ist auch eine Zuweisungsanweisung. Da die bloße Tatsache, dass der Name dem Namen zugewiesen wird, ihn lokal für die Funktion macht, versucht Ihre += -Anweisung, eine lokale Variable zu verwenden, die noch nicht zugewiesen wurde. Dadurch wird ein UnboundLocalError ausgelöst.

Wenn Sie alle drei dieser x Referenzen auf die globale Variable beziehen möchten, müssen Sie global x sowohl in der counter als auch in der temp Funktion ausführen. In Python 3.x (aber nicht 2.x) gibt es eine nonlocal -Deklaration, ähnlich wie global , die Sie verwenden können, um temp der Variablen in counter zuzuweisen, aber die globale x zu belassen allein.

    
Thomas Wouters 29.05.2011 23:33
quelle
2

Die Python-Dokumentation beantwortet die Frage im Detail: Ссылка

Zusammenfassend hat Python statische Scoping-Regeln. Wenn die Funktion f einen Variablennamen definiert oder löscht, bezieht sich der Variablenname auf eine Variable im Abschluss der Funktion f. Wenn Funktion f nur einen Variablennamen (keine Definition oder Löschung) verwendet, bezieht sich der Name auf den Namen des übergeordneten Bereichs von f. Fahren Sie mit übergeordneten Bereichen fort, bis eine Definition gefunden wird oder Sie den globalen Geltungsbereich erreichen. Zum Beispiel:

%Vor%

Das Schlüsselwort global und (in Python 3) die Schlüsselwörter nonlocal überschreiben die Standard-Bereichsregeln.

Während Variablen Namen statisch aufgelöst werden, werden Variablen Werte dynamisch aufgelöst. Der Wert der Variablen ergibt sich aus der letzten Definition oder Löschung dieser Variablen zum Zeitpunkt des Zugriffs auf die Variable. Werte werden in der Funktion closey nachgeschlagen, in der sich die Variable befindet.

    
Heatsink 29.05.2011 23:37
quelle
2

Closures in Python sind nicht beschreibbar, daher können Sie Ihren Code nicht auf diese Weise schreiben. Wenn Sie nur von der Variablen innerhalb der Funktionen lesen, sollten Sie gut sein. In Python 3 könnten Sie das Schlüsselwort nonlocal verwenden, um das gewünschte Verhalten zu erhalten.

Wenn Sie Python 2.5 oder höher verwenden, können Sie auch den Schlüssel yield verwenden, um den obigen Code als Generator zu schreiben.

    
AHM 29.05.2011 23:30
quelle
1

Danke für all Ihre Antworten. Für den Fall, dass sich jemand darum kümmert, habe ich eine Lösung für dieses Problem gefunden. Ich habe es geschafft, indem ich eine "scoper" -Funktion erstellt habe, um eine Zählervariable zu erstellen.

%Vor%

Das oben Genannte erlaubte mir dies zu tun, was richtige Schließungen nachahmt:

%Vor%     
amatsukawa 30.05.2011 08:04
quelle

Tags und Links