UnboundLocalError bei der Manipulation von Variablen ergibt inkonsistentes Verhalten

In Python funktioniert der folgende Code:

a = 1 b = 2 def test(): print a, b test() 

Und der folgende Code funktioniert:

 a = 1 b = 2 def test(): if a == 1: b = 3 print a, b test() 

Aber das folgende funktioniert nicht :

 a = 1 b = 2 def test(): if a == 1: a = 3 print a, b test() 

Das Ergebnis dieses letzten Blocks ist eine UnboundLocalError Nachricht, wobei a vor der Zuweisung referenziert wird.

Ich verstehe, dass ich die letzte Blockarbeit machen kann, wenn ich global a in der test() Definition addiere, also weiß es, wem ich rede.

Warum bekomme ich keinen Fehler bei der Zuordnung eines neuen Wertes zu b ?

Bin ich eine lokale b Variable, und es schreit mich nicht an, weil ich nicht versuche, es vor der Zuweisung zu verweisen?

Aber wenn das der Fall ist, warum kann ich print a, b im Falle des ersten Blocks print a, b , ohne vorher ein global a, b zu deklarieren?

3 Solutions collect form web for “UnboundLocalError bei der Manipulation von Variablen ergibt inkonsistentes Verhalten”

Lassen Sie mich Ihnen den Link zu den Dokumenten geben, wo es eindeutig erwähnt wird.

Wenn eine Variable einen neuen Wert irgendwo innerhalb des Körpers der Funktion zugewiesen wird, wird davon ausgegangen, dass sie eine lokale ist .

(Betonung meiner)

Also ist deine Variable a eine lokale Variable und nicht global. Dies ist, weil Sie eine Zuweisungsanweisung haben,

 a = 3 

In der dritten Zeile deines Codes. Dies macht eine lokale Variable. Und unter Bezugnahme auf die lokale Variable vor der Deklaration verursacht einen Fehler, der ein UnboundLocalError .

Allerdings in Ihrem 2. Code-Block, machen Sie keine solchen Zuweisungsanweisungen und daher erhalten Sie keinen solchen Fehler.

Ein weiterer nützlicher Link ist das

Wird angehoben, wenn auf eine lokale Variable in einer Funktion oder Methode verwiesen wird, aber kein Wert an diese Variable gebunden ist.

Sie beziehen sich also auf die lokale Variable, die Sie in der nächsten Zeile erstellen.

Um dies zu verhindern gibt es zwei Möglichkeiten

  • Gute Weg – Übergeben von Parametern

    Definiere deine Funktion als def test(a): und nenn es als test(a)

  • Schlechter Weg – mit global

    Habe eine Linie global a an der Spitze deines Funktionsaufrufs.

Python Scoping Regeln sind ein wenig heikel! Sie müssen sie beherrschen, um die Sprache zu ergattern. Schau dir das an

Im dritten Block hat der Compiler als eine lokale Variable markiert, da er zugewiesen wird, also wenn er in dem Ausdruck verwendet wird, den er im lokalen Bereich sucht. Da es dort nicht existiert, wird eine Ausnahme erhoben.

Im zweiten Block hat der Compiler b als lokale Variable markiert, aber nicht a , daher gibt es keine Ausnahme, wenn auf a Zugriff zugegriffen wird, da äußere Bereiche gesucht werden.

Wenn Sie a ändern, wird es eine lokale Variable. Wenn du es einfach rezitierst, ist es ein globales. Sie haben im lokalen Bereich keine A definiert, also können Sie es nicht ändern.

Wenn du eine globale ändern willst, musst du sie global in deinem lokalen Bereich anrufen.

Werfen Sie einen Blick auf den Bytecode für die folgenden

 import dis a = 9 # Global def foo(): print a # Still global def bar(): a += 1 # This "a" is local dis.dis(foo) 

Ausgabe:

  2 0 LOAD_GLOBAL 0 (a) 3 PRINT_ITEM 4 PRINT_NEWLINE 5 LOAD_CONST 0 (None) 8 RETURN_VALUE 

Für die zweite Funktion:

 dis.dis(bar) 

Ausgabe:

  2 0 LOAD_FAST 0 (a) 3 LOAD_CONST 1 (1) 6 INPLACE_ADD 7 STORE_FAST 0 (a) 10 LOAD_CONST 0 (None) 13 RETURN_VALUE 

Der Bytecode der ersten Funktion lädt die globale a ( LOAD_GLOBAL ), weil sie nur referenziert wird. Der Bytecode der zweiten Funktion ( LOAD_FAST ) versucht , eine lokale a zu laden, aber man wurde nicht definiert.

Der einzige Grund, warum deine zweite Funktion funktioniert, ist, weil a gleich 1 . Wenn a war etwas aber 1 , würde die lokale Zuordnung zu b nicht passieren und Sie würden den gleichen Fehler erhalten.

  • String mit 'f' Präfix in python-3.6
  • Was bedeutet Umfang
  • "Lokale Variable referenziert vor Zuordnung" - nur Funktionen?
  • Warum ist eine Klassenvariable nicht im Listenverständnis definiert, sondern eine andere ist?
  • Warum erbt keine Unterfunktion den Bereich in Python?
  • Kurze Beschreibung der Scoping Regeln?
  • Pythonumfang [doppelte]
  • Warum verschachtelte Funktionen auf Variablen von äußeren Funktionen zugreifen können, aber sie nicht ändern dürfen [duplizieren]
  • Python überschreibt Variablen in verschachtelten Funktionen
  • Variabler Bereich (Python Newbie)
  • Python Variable Scope (Vorbehalt durch Verweis oder Kopie?)
  • Python ist die beste Programmiersprache der Welt.