@Joa:
Dass mein Beispiel bei Dir funktioniert muss an Deiner Anpassung liegen

!
Auf numerix' Beitrag hin konnte ich natürlich nicht mehr ruhig sitzen und musste mein Beispiel nochmal durchkauen.
Auch wenn es vorerst so aussieht, als würde es funktionieren, tauchen ganz ganz fiese Gemeinheiten auf:
- Nach dem ersten Aufruf von 'switch()' funktioniert alles, nachdem 'started' auf False zeigt wird 'start_ani()' aufgerufen.
- Innerhalb von 'start_ani()' wird 'started' auf True gesetzt, ein erneuter Aufruf von 'switch()' sollte demnach 'stop_ani()' starten. Passiert aber nicht!
- Ich ziehe also meine Wunderwaffe 'print' aus dem Ärmel

und füge gleich als erste Zeile ein 'print started' sowohl in 'switch()' als auch in 'start_ani()' ein.
Code: Alles auswählen
started = False
def switch():
print started
if started:
stop_ani()
else:
start_ani()
def start_ani():
print started
started = True
print 'gestartet'
def stop_ani():
started = False
print 'gestoppt'
- Genau jetzt beginnt mein Leidensweg: Ich rufe 'switch()' auf und erhalte
Code: Alles auswählen
In [62]: switch()
False
-------------------------------------------------------
10 def start_ani():
---> 11 print started
12 started = True
13 print 'gestartet'
UnboundLocalError: local variable 'started' referenced before assignment
Wie kann das sein

? Weshalb funktioniert 'print started' in 'switch()', wirft aber in 'start_ani()' einen 'UnboundLocalError'?
'switch()' sucht zuerst im lokalen Namensraum nach 'started' und findet dort den Namen nicht. Deshalb schaut es im globalen Namensraum (auf Modulebene) nach, findet dort den (globalen) Namen 'started', gibt 'False' aus und verzweigt zu 'start_ani()'.
Warum meckert 'start_ani()', dass es den lokalen Namen 'started' nicht findet? 'switch()' hat doch nach dem lokalen auch im globalen Namensraum gesucht?
Es muss wohl daran liegen, dass der Interpreter durch die Anweisung 'started = True' innerhalb von 'start_ani()' einen lokalen Namen 'started' anlegt. Wenn dann während der Ausführung von 'start_ani()' die print-Anweisung 'started' ausgeben möchte, wird wohl der (lokale) Name gefunden, allerdings ist dieser Name noch 'zeigerlos', da ein Verweis erst eine Zeile danach stattfindet.
Fazit: Das Problem an meinem Beispiel ist also, dass 'switch()' auf den globalen Namen 'started' (False) zugreift, 'start_ani()' und 'stop_ani()' aber jeweils ihren eigenen lokalen Namen 'started' setzen und auch gleich danach wieder verlieren, da Funktionen nach ihrem Ende ihre lokalen Namen nicht behalten.
Letztlich verwendet mein Beispiel also 3 Namen 'started', die miteinander in keiner Verbindung stehen, obwohl sie den selben Namen tragen.
Sauber wäre also folgendes:
Code: Alles auswählen
def switch(started):
if started:
started = stop_ani()
else:
started = start_ani()
return started
def start_ani():
print 'gestartet'
return True
def stop_ani():
print 'gestoppt'
return False
In [67]: started = False
In [68]: started = switch(started)
gestartet
In [69]: started = switch(started)
gestoppt
In [70]: started = switch(started)
gestartet
mutetella