Seite 1 von 1

finally kann trickreich sein

Verfasst: Sonntag 23. Januar 2011, 23:01
von sma
Schnell, ohne es im Interpreter auszuprobieren, was liefert dieses Programm:

Code: Alles auswählen

def a():
    while True:
        try: raise ValueError
        finally: break
a()
Wirft es eine Exception? Endet es überhaupt? Und warum ist es, wie es ist?

Stefan

Re: finally kann trickreich sein

Verfasst: Sonntag 23. Januar 2011, 23:08
von derdon
Hm, also bei mir passierte genau das, was ich auch erwartete: RuntimeError weil das Rekursionslimit erreicht wurde. Natürlich nachdem ich die Einrückung korrigiert habe ;)

Endlosschleife wird gestartet, finally wird ausgeführt, Endlosschleife wird beendet, a ruft sich selbst auf und startet Endlosschleife erneut, finally wird ausgeführt, Endlosschleife wird beendet, und so weiter und so fort

Was hast du denn erwartet und warum?


Edit: genau genommen passiert nicht viel, wenn die Funktion nur definiert wird, aber nicht aufgerufen :twisted:

Re: finally kann trickreich sein

Verfasst: Sonntag 23. Januar 2011, 23:14
von derdon
Oh, jetzt verstehe ich, was du meinst. finally-break schein ein Spezialfall zu sein:

Code: Alles auswählen

>>> while True:
...     try:
...         raise Exception()
...     finally:
...         print 'boh'
... 
boh
Traceback (most recent call last):
  File "<input>", line 3, in <module>
Exception
>>> while True:
...     try:
...         raise Exception()
...     finally:
...         break
... 
>>> 

Re: finally kann trickreich sein

Verfasst: Sonntag 23. Januar 2011, 23:17
von /me
Ich habe es mal ausprobiert (Python 2.6).

Das Programm beendet sich sehr schnell ohne Fehlermeldung. Ich würde einen ValueError erwarten, aber der wird anscheinend irgendwie von der Schleife oder dem break gefressen.

Re: finally kann trickreich sein

Verfasst: Sonntag 23. Januar 2011, 23:20
von Darii
sma hat geschrieben:Und warum ist es, wie es ist?
Vermutlich weil der finally-Block sicherstellen soll, dass der Code in ihm in jedem Fall ausgeführt wird. Das ginge bei return, raise oder break schlecht, wenn die Ausnahme nicht abgefangen würde.

Re: finally kann trickreich sein

Verfasst: Sonntag 23. Januar 2011, 23:23
von bords0
Ist konsistent mit "die zwischengespeicherte Exception wird wieder geraised, wenn das Ende des finally-Blocks erreicht wird" - das Ende des finally-Blocks wird eben nicht erreicht.

Lustig auch (ungetestet):

Code: Alles auswählen

def a():
    try:
        return
    finally:
        a()

Re: finally kann trickreich sein

Verfasst: Sonntag 23. Januar 2011, 23:25
von sma
/me hat geschrieben:Ich habe es mal ausprobiert (Python 2.6).
Hey, ausprobieren ist schummeln :) Wenn man's ausprobiert hat, kann man sich's erklären, finde ich, aber ich hätte das auf den ersten Blick nicht vermutet.

Stefan

Re: finally kann trickreich sein

Verfasst: Sonntag 23. Januar 2011, 23:27
von sma
@bords0: Sorry, hatte die Einrückung verpatzt. Die von dir vermutete Endlosrekursion durch Aufruf von a() in finally wollte ich nicht konstruieren. Das a() sollte die Funktion einfach nur aufrufen, damit überhaupt etwas passiert.

Stefan

Re: finally kann trickreich sein

Verfasst: Sonntag 23. Januar 2011, 23:37
von bords0
Missverständnis :-)

Ich hatte nur darauf hinweisen wollen, dass finally selbst bei "return" im "try:" ausgeführt wird.

Für die Endlosschleife darf bei dir das "a()" natürlich nicht im finally-Zweig (d.h. hinter dem break) stehen, sondern auf Funktionsebene (so habe ich auch derdon verstanden).

Re: finally kann trickreich sein

Verfasst: Montag 24. Januar 2011, 08:46
von lunar
Language Reference, Abschnitt 7.4 The try statement:
If finally is present, it specifies a ‘cleanup’ handler. The try clause is executed, including any except and else clauses. If an exception occurs in any of the clauses and is not handled, the exception is temporarily saved. The finally clause is executed. If there is a saved exception, it is re-raised at the end of the finally clause. If the finally clause raises another exception or executes a return or break statement, the saved exception is lost. The exception information is not available to the program during execution of the finally clause.

When a return, break or continue statement is executed in the try suite of a try...finally statement, the finally clause is also executed ‘on the way out.’ A continue statement is illegal in the finally clause. (The reason is a problem with the current implementation — this restriction may be lifted in the future).
Irgendwie muss man "break" und "return" innerhalb eines "finally"-Blocks ja sinnvolle Semantik verleihen.

Re: finally kann trickreich sein

Verfasst: Montag 24. Januar 2011, 16:17
von DasIch
Bin ich eigentlich der einzige der dieses Verhalten absolut logisch und einfach nachvollziehbar findet? Das einzige was wirklich seltsam ist, ist dass `continue` im `finally` Block nicht erlaubt ist.

Wenn man `return`, `break` und `raise` im `finally` Block erlaubt müssen die, da als letztes ausgeführt, Priorität über die Anweisungen im `try` Block haben, alles andere wäre seltsam es sei den man führt den `finally` Block nicht aus. Letzteres mag sinnvoll sein ist allerdings definitiv unpraktisch.

Re: finally kann trickreich sein

Verfasst: Montag 24. Januar 2011, 23:49
von Darii
DasIch hat geschrieben:Bin ich eigentlich der einzige der dieses Verhalten absolut logisch und einfach nachvollziehbar findet?
Nein, der Meinung sind hier wohl alle.