Wie findet der Zugriff auf Referenzen statt?

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
template
User
Beiträge: 29
Registriert: Mittwoch 21. November 2007, 09:44

Hallo zusammen,

ich habe ein Verhalten in Python welches ich nicht verstehe.

Code: Alles auswählen

#!/usr/bin/env python
THISISAGLOBAL = 25

def func1():
	print THISISAGLOBAL

def func2():
	THISISAGLOBAL = 30
	print THISISAGLOBAL

def func3():
	global THISISAGLOBAL
	THISISAGLOBAL = 30
	print THISISAGLOBAL
	
def func4():
	global THISISAGLOBAL

	if 1 == 0:
		THISISAGLOBAL = ISNOTEXECUTED
	print THISISAGLOBAL

def func5():
	if 1 == 0:
		locals()['THISISAGLOBAL'] = ISNOTEXECUTED
	print THISISAGLOBAL
	
def func6():
	if 1 == 0:
		THISISAGLOBAL = 1
	print THISISAGLOBAL

	
func1()
func2()
func1()
func3()
func1()
func4()
func5()
func6()
Der Code liefert hierbei folgende ausgabe:

Code: Alles auswählen

25
30
25
30
30
30
30
Traceback (most recent call last):
  File "./globaltest.py", line 41, in ?
    func6()
  File "./globaltest.py", line 31, in func6
    print THISISAGLOBAL
UnboundLocalError: local variable 'THISISAGLOBAL' referenced before assignment
Ich dachte nun eigentlich, dass der Identifier immer zuerst in den locals gesucht wird und wenn er hier nicht gefunden wird in den globals. Nun hat aber die, nicht durchlaufene, Zuweisung in func6 anscheinend zur Konsequenz, das der Zugriff auf THISISAGLOBAL hier nicht mehr bei den globals versucht wird. Warum?

Vielen herzlichen dank im voraus
template
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

In `func6` wird dein "global" auch als local benutzt und damit als local betrachtet, da die Zuweisung aber nicht ausgefuehrt wird, bleibt der Name ungebunden.

Und hier noch ein Fall, der dir fehlt:

Code: Alles auswählen

In [1]: GLOB = 23

In [2]: def func7():
   ...:     print GLOB
   ...:     GLOB = 5
   ...:     

In [3]: func7()
---------------------------------------------------------------------------
UnboundLocalError                         Traceback (most recent call last)
<ipython-input-3-2664cf86600a> in <module>()
----> 1 func7()

<ipython-input-2-315cea9167d1> in func7()
      1 def func7():
----> 2     print GLOB
      3     GLOB = 5
      4 

UnboundLocalError: local variable 'GLOB' referenced before assignment
Hier koennte man sagen, dass das doch kein Problem sein sollte, aber wie schon oben erwaehnt: GLOB wird als local betrachtet und damit gibt es `GLOB` vor der Zuweisung nicht.
BlackJack

@template: Wenn *irgendwo* innerhalb der Funktion eine Zuweisung an einen Namen geschieht, dann ist der Name lokal, ausser man deklariert ihn mit ``global`` als Modulglobal. Diese Entscheidung geschieht schon beim Übersetzen des Quelltextes und nicht erst bei der Ausführung.
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Ergaenzend hierzu der Bytecode:

Code: Alles auswählen

In [1]: import dis

In [2]: def func7():
    print GLOB
    GLOB = 5
   ...:     

In [3]: dis.dis(func7)
  2           0 LOAD_FAST                0 (GLOB)
              3 PRINT_ITEM          
              4 PRINT_NEWLINE       

  3           5 LOAD_CONST               1 (5)
              8 STORE_FAST               0 (GLOB)
             11 LOAD_CONST               0 (None)
             14 RETURN_VALUE        

In [4]: def func1():
   ...:             print THISISAGLOBAL
   ...:     

In [5]: dis.dis(func1)        
  2           0 LOAD_GLOBAL              0 (THISISAGLOBAL)
              3 PRINT_ITEM          
              4 PRINT_NEWLINE       
              5 LOAD_CONST               0 (None)
              8 RETURN_VALUE  
template
User
Beiträge: 29
Registriert: Mittwoch 21. November 2007, 09:44

Vielen dank für die ausführlichen Erklärungen. Jetzt hab ichs kappiert. Ich hatte mich immer auf die Grundregel gestellt, das Python-Code "durchlaufen" werden muss, um einfluss auf den Ablauf zu haben, aber wie ich jetzt gelernt habe, gibt es auch ausnahmen von der Regel. :)
Antworten