Rückkehr frisst Ausnahme
Frage
Ich fand das folgende Verhalten zumindest seltsam :
def errors():
try:
ErrorErrorError
finally:
return 10
print errors()
# prints: 10
# It should raise: NameError: name 'ErrorErrorError' is not defined
Die Ausnahme verschwindet, wenn Sie return
in einer finally
-Klausel verwenden. Ist das ein Fehler? Ist das dokumentiert überall?
Aber die eigentliche Frage (und die Antwort werde ich als richtig markieren) ist:
Was ist der Grund Python-Entwickler, dass merkwürdiges Verhalten zu erlauben?
Lösung
Sie haben gefragt, über den Python-Entwickler Argumentation. Ich kann nicht für sie sprechen, aber kein anderes Verhalten macht Sinn. Eine Funktion kann entweder einen Wert zurückgeben, oder es kann eine Ausnahme auslösen; es kann nicht beides tun. Der Zweck einer „endlich“ Klausel ist Bereinigungscode zu schaffen, die „garantiert“, unabhängig von Ausnahmen ausgeführt werden sollten. Indem eine return-Anweisung in einer finally-Klausel, haben Sie erklärt, dass Sie einen Wert zurückgeben wollen, egal was passiert, und zwar unabhängig von Ausnahmen. Wenn Python verhielt sich wie Sie fragen, und hob die Ausnahme, wäre es, den Vertrag der „endlich“ Klausel brechen (weil es fehlschlagen würde den Wert zurückkehren Sie ihm gesagt zurückzukehren).
Andere Tipps
Die Ausnahme verschwindet, wenn Sie
return
in einerfinally
-Klausel verwenden. .. Ist das dokumentiert überall?
Wenn schließlich vorhanden ist, es gibt eine ‚Bereinigung‘ Handler. Die try-Klausel ausgeführt wird, einschließlich aller mit Ausnahme und else-Klauseln. Wenn eine Ausnahme in eine der Klauseln auftritt und nicht behandelt wird, wird die Ausnahme vorübergehend gespeichert. Die finally-Klausel wird ausgeführt. Wenn eine gespeicherte Ausnahme ist, wird am Ende der finally-Klausel erneut angehoben. Wenn die finally-Klausel eine andere Ausnahme auslöst oder führt eine Rückkehr oder eine Erklärung brechen, die gespeicherte Ausnahme verloren.
Hier ist ein interessanter Vergleich zur Rückkehr in finally-Block unter - Java / C # / Python / JavaScript: ( Archiv-Link )
Return From Schließlich
Gerade heute habe ich mit einigen Fehlern in Java half und stieß auf interessantes Problem - was ist, wenn Sie verwenden Rückkehr in try / catch geschieht Aussage? Sollte der schließlich Abschnitt feuern oder nicht? Ich vereinfacht die Problem folgenden Code-Snippet:
Was bedeutet die folgenden Code ausdrucken?
class ReturnFromFinally { public static int a() { try { return 1; } catch (Exception e) {} finally{ return 2; } } public static void main(String[] args) { System.out.println(a()); } }
Meine erste Vermutung wäre, dass es
1
drucken soll, ich rufereturn
, so nehme ich an, wird ein zurückgeführt. Es ist jedoch nicht die Fall:Ich verstehe die Logik, schließlich Abschnitt ausgeführt werden muss, aber irgendwie fühle ich mich unbehaglich darüber. Mal sehen, was C # funktioniert in diesem Fall:
class ReturnFromFinally { public static int a() { try { return 1; } catch (System.Exception e) {} finally { return 2; } } public static void Main(string[] args) { System.Console.WriteLine(a()); } }
Ich ziehe es viel lieber dieses Verhalten, Kontrollfluss kann nicht mit messed werden in finally, so verhindert, dass es uns ourself in dem von der Aufnahme Fuß. Nur aus Gründen der Vollständigkeit, lassen Sie uns überprüfen, was andere Sprachen tun.
Python:
def a(): try: return 1 finally: return 2 print a()
JavaScript:
<script> function ReturnFromFinally() { try { return 1; } catch (e) { } finally { return 2; } } </script> <a onclick="alert(ReturnFromFinally());">Click here</a>
Es gibt keine finally in C ++ und PHP, also kann ich nicht die letzte ausprobieren zwei Sprachen Ich habe Compiler / Interpreter für.
Unser kleines Experiment schön zeigte, dass C # den schönsten Ansatz hat für dieses Problem war, aber ich ziemlich überrascht zu erfahren, dass alle andere Sprachen umgehen das Problem auf die gleiche Weise.
von einer endlich Rückkehr ist nicht eine gute Idee. Ich weiß, C # speziell diese verbietet tun.