scope bei lokalen funktionsdefinitionen

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
behe0815
User
Beiträge: 4
Registriert: Mittwoch 27. September 2006, 11:59

Hallo!

Folgender code gibt 'muh' aus, ich hatte gerne 'hum' :P

Code: Alles auswählen

def test():
	a = 0
	
	def f1():
		a = 1
		return
	
	def f2():
		if (a == 1):
			print 'hum'
		else:
			print 'muh'
		return

	f1()
	f2()
	
	return
	
test()
Wie kann ich f1() und f2() dazu bringen, die in test() deklarierte variable a zu verwenden, und nicht eine eigene variable a lokal anzulegen?

Geht das ueberhaupt? Konkret will ich in test() lokal einige funktionen definieren, die ich einem expat xml parser uebergebe. Diese funktionen sollen aber auf lokale variablen von test() zugreifen koennen.

Behe0815
Monk
User
Beiträge: 16
Registriert: Montag 28. August 2006, 11:27

Einfach global benutzen...

Code: Alles auswählen

def test(): 
    a = 0 
    
    def f1(): 
        global a
        a = 1 
        return 
    
    def f2(): 
        global a
        if (a == 1): 
            print 'hum' 
        else: 
            print 'muh' 
        return 

    f1() 
    f2() 
    
    return 
    
test() 
Ergebnis:

Code: Alles auswählen

>>> hum
Gruß, der Monk
Nirven
User
Beiträge: 130
Registriert: Mittwoch 10. Mai 2006, 08:18
Wohnort: Bremerhaven

Lieber so, auf global verzichten wenn es geht.

Code: Alles auswählen

def test():
    a = 0
   
    def f1(a):
        
        a = 1
        return a
   
    def f2(a):
        
        if (a == 1):
            print 'hum'
        else:
            print 'muh'
        return

    a = f1(a)
    f2(a)
   
    return
   
test()
Monk
User
Beiträge: 16
Registriert: Montag 28. August 2006, 11:27

Geht nur leider nicht, wenn er Callback-Funktionen für eine externe API (expat) definiert. Da muss dann doch global her, oder...

Code: Alles auswählen

class CallBackHost:
    def __init__(self):
        self.a = 0

    def f1(self):
        self.a = 1

    def f2(self):
        if (a == 1): 
            print 'hum' 
        else: 
            print 'muh' 
        return 
        
if __name__ == "__main__":
    c = CallBackHost()
    c.f1()
    f = c.f2
    # f wird uebergeben und folgende Zeile
    # von der externen API ausgefuehrt
    f()
Wenn Du alles in eine Klasse einbettest, hast Du genau die benötigte Funktionalität ohne globale Variablen. Der Parameter self wird durch die Bindung an c automatisch vom Interpreter übergeben.

Gruß, der Monk
behe0815
User
Beiträge: 4
Registriert: Mittwoch 27. September 2006, 11:59

Danke fuer die Tipps, "global" war mir bis dato unbekannt, hat aber leider in meinem realen Sourcecode nicht funktioniert. Keine Ahnung warum.

Aber mit der Hilfsklasse, wie sie Monk vorgeschlagen hat, funktioniert es ohne Probleme. Also sind in Python Klassenmethoden ebenso wie normale Funktionen als Callbacks verwendbar. Das ist doch mal gut zu wissen.

Nochmals tausend Dank. :D
mitsuhiko
User
Beiträge: 1790
Registriert: Donnerstag 28. Oktober 2004, 16:33
Wohnort: Graz, Steiermark - Österreich
Kontaktdaten:

behe0815 hat geschrieben:Danke fuer die Tipps, "global" war mir bis dato unbekannt, hat aber leider in meinem realen Sourcecode nicht funktioniert. Keine Ahnung warum.
Wäre auch besser es funktioniere nicht. Das ist grob fahrlässig. Und ganz sicher nicht Thread safe... :roll:

probiers so:

Code: Alles auswählen

def foo():
 ns = {'a': 42}
 def inc():
  ns['a'] += 1
 def prr():
  print ns['a']
 inc()
 inc()
 inc()
 prr()

foo()
TUFKAB – the user formerly known as blackbird
Benutzeravatar
birkenfeld
Python-Forum Veteran
Beiträge: 1603
Registriert: Montag 20. März 2006, 15:29
Wohnort: Die aufstrebende Universitätsstadt bei München

... und ich darf noch anmerken, dass "return" am Ende einer Funktion ziemlich sinnfrei ist.
Antworten