Ist es eine gute Praxis, try-außer-else in Python zu verwenden?

437

Von Zeit zu Zeit sehe ich in Python den Block:

try:
   try_this(whatever)
except SomeException as exception:
   #Handle exception
else:
   return something

Was ist der Grund für das Bestehen des Try-außer-else?

Ich mag diese Art der Programmierung nicht, da sie Ausnahmen verwendet, um die Flusskontrolle durchzuführen. Wenn es jedoch in der Sprache enthalten ist, muss es einen guten Grund dafür geben, nicht wahr?

Nach meinem Verständnis handelt es sich bei Ausnahmen nicht um Fehler , und sie sollten nur unter außergewöhnlichen Bedingungen verwendet werden (z. B. versuche ich, eine Datei auf die Festplatte zu schreiben, und es ist kein Speicherplatz mehr vorhanden, oder ich habe möglicherweise keine Berechtigung) und nicht für den Datenfluss Steuerung.

Normalerweise behandle ich Ausnahmen wie folgt:

something = some_default_value
try:
    something = try_this(whatever)
except SomeException as exception:
    #Handle exception
finally:
    return something

Oder wenn ich wirklich nichts zurückgeben möchte, wenn eine Ausnahme auftritt, dann:

try:
    something = try_this(whatever)
    return something
except SomeException as exception:
    #Handle exception
Juan Antonio Gomez Moriano
quelle

Antworten:

665

"Ich weiß nicht, ob es aus Unwissenheit ist, aber ich mag diese Art der Programmierung nicht, da sie Ausnahmen verwendet, um die Flusskontrolle durchzuführen."

In der Python-Welt ist die Verwendung von Ausnahmen für die Flusskontrolle üblich und normal.

Sogar die Python-Kernentwickler verwenden Ausnahmen für die Flusskontrolle, und dieser Stil ist stark in die Sprache eingebunden (dh das Iteratorprotokoll verwendet StopIteration , um die Beendigung der Schleife zu signalisieren).

Darüber hinaus wird der Try-Except-Style verwendet, um die Rennbedingungen zu verhindern, die einigen der "Look-before-you-leap" -Konstrukte inhärent sind . Wenn Sie beispielsweise os.path.exists testen, erhalten Sie Informationen, die zum Zeitpunkt der Verwendung möglicherweise veraltet sind. Ebenso gibt Queue.full Informationen zurück, die möglicherweise veraltet sind. Der Try-außer-else-Stil erzeugt in diesen Fällen zuverlässigeren Code.

"Nach meinem Verständnis sind Ausnahmen keine Fehler, sie sollten nur für außergewöhnliche Bedingungen verwendet werden."

In einigen anderen Sprachen spiegelt diese Regel ihre kulturellen Normen wider, wie sie sich in ihren Bibliotheken widerspiegeln. Die "Regel" basiert teilweise auch auf Leistungsüberlegungen für diese Sprachen.

Die Python-Kulturnorm ist etwas anders. In vielen Fällen Sie müssen Ausnahmen für Steuerfluss verwenden. Außerdem verlangsamt die Verwendung von Ausnahmen in Python den umgebenden Code und den aufrufenden Code nicht wie in einigen kompilierten Sprachen (dh CPython implementiert bereits Code für die Ausnahmeprüfung bei jedem Schritt, unabhängig davon, ob Sie tatsächlich Ausnahmen verwenden oder nicht).

Mit anderen Worten, Ihr Verständnis, dass "Ausnahmen für das Außergewöhnliche sind", ist eine Regel, die in einigen anderen Sprachen sinnvoll ist, jedoch nicht für Python.

"Wenn es jedoch in der Sprache selbst enthalten ist, muss es einen guten Grund dafür geben, nicht wahr?"

Ausnahmen sind nicht nur hilfreich, um Rennbedingungen zu vermeiden, sondern auch sehr nützlich, um die Fehlerbehandlung außerhalb von Schleifen durchzuführen. Dies ist eine notwendige Optimierung in interpretierten Sprachen, die keine automatische schleifeninvariante Codebewegung aufweisen .

Außerdem können Ausnahmen den Code in häufigen Situationen, in denen die Fähigkeit zur Behandlung eines Problems weit entfernt von dem Ort ist, an dem das Problem aufgetreten ist, erheblich vereinfachen. Beispielsweise ist es üblich, dass Benutzeroberflächencode der obersten Ebene Code für die Geschäftslogik aufruft, der wiederum Routinen auf niedriger Ebene aufruft. Situationen, die in Routinen auf niedriger Ebene auftreten (z. B. doppelte Datensätze für eindeutige Schlüssel bei Datenbankzugriffen), können nur im Code der obersten Ebene behandelt werden (z. B. Aufforderung an den Benutzer nach einem neuen Schlüssel, der nicht mit vorhandenen Schlüsseln in Konflikt steht). Die Verwendung von Ausnahmen für diese Art von Kontrollfluss ermöglicht es den Routinen der mittleren Ebene, das Problem vollständig zu ignorieren und sich von diesem Aspekt der Flusskontrolle gut zu entkoppeln.

Es gibt hier einen schönen Blog-Beitrag über die Unentbehrlichkeit von Ausnahmen .

Siehe auch diese Antwort zum Stapelüberlauf: Sind Ausnahmen wirklich für außergewöhnliche Fehler?

"Was ist der Grund für den Versuch - außer - sonst zu existieren?"

Die else-Klausel selbst ist interessant. Es wird ausgeführt, wenn es keine Ausnahme gibt, jedoch vor der finally-Klausel. Das ist sein Hauptzweck.

Ohne die else-Klausel wäre die einzige Möglichkeit, zusätzlichen Code vor der Finalisierung auszuführen, die ungeschickte Praxis, den Code zur try-Klausel hinzuzufügen. Das ist umständlich, da die Gefahr besteht, dass Ausnahmen in Code ausgelöst werden, die nicht durch den try-Block geschützt werden sollten.

Der Anwendungsfall, vor der Finalisierung zusätzlichen ungeschützten Code auszuführen, tritt nicht sehr häufig auf. Erwarten Sie also nicht viele Beispiele im veröffentlichten Code. Es ist etwas selten.

Ein weiterer Anwendungsfall für die else-Klausel besteht darin, Aktionen auszuführen, die ausgeführt werden müssen, wenn keine Ausnahme auftritt, und die nicht auftreten, wenn Ausnahmen behandelt werden. Zum Beispiel:

recip = float('Inf')
try:
    recip = 1 / f(x)
except ZeroDivisionError:
    logging.info('Infinite result')
else:
    logging.info('Finite result')

Ein anderes Beispiel tritt bei unittest Läufern auf:

try:
    tests_run += 1
    run_testcase(case)
except Exception:
    tests_failed += 1
    logging.exception('Failing test case: %r', case)
    print('F', end='')
else:
    logging.info('Successful test case: %r', case)
    print('.', end='')

Schließlich wird eine else-Klausel in einem try-Block am häufigsten für eine gewisse Verschönerung verwendet (Ausrichten der außergewöhnlichen Ergebnisse und nicht außergewöhnlichen Ergebnisse auf derselben Einrückungsstufe). Diese Verwendung ist immer optional und nicht unbedingt erforderlich.

Raymond Hettinger
quelle
28
"Das ist ungeschickt, weil es die Gefahr birgt, Ausnahmen in Code auszulösen, die nicht durch den try-Block geschützt werden sollten." Dies ist das wichtigste Lernen hier
Felix Dombek
2
Danke für die Antwort. Für Leser, die nach Beispielen für die Verwendung von try-without-else suchen, schauen Sie sich die copyfile-Methode von shutil an: github.com/python/cpython/blob/master/Lib/shutil.py#L244
suripoori
2
Der Punkt ist, dass die else-Klausel nur ausgeführt wird, wenn die try-Klausel erfolgreich ist.
Jonathan
172

Was ist der Grund für das Bestehen des Try-außer-else?

Mit einem tryBlock können Sie einen erwarteten Fehler behandeln. Der exceptBlock sollte nur Ausnahmen abfangen, für die Sie bereit sind. Wenn Sie einen unerwarteten Fehler behandeln, kann Ihr Code das Falsche tun und Fehler verbergen.

Eine elseKlausel wird ausgeführt, wenn keine Fehler aufgetreten sind. Wenn Sie diesen Code nicht im tryBlock ausführen, vermeiden Sie, dass ein unerwarteter Fehler auftritt. Auch hier kann das Abfangen eines unerwarteten Fehlers Fehler verbergen.

Beispiel

Zum Beispiel:

try:
    try_this(whatever)
except SomeException as the_exception:
    handle(the_exception)
else:
    return something

Die Suite "try, without" enthält zwei optionale Klauseln elseund finally. So ist es eigentlich try-except-else-finally.

elsewird nur ausgewertet, wenn es keine Ausnahme vom tryBlock gibt. Dies ermöglicht es uns, den komplizierteren Code unten zu vereinfachen:

no_error = None
try:
    try_this(whatever)
    no_error = True
except SomeException as the_exception:
    handle(the_exception)
if no_error:
    return something

Wenn wir also eine elsemit der Alternative vergleichen (was zu Fehlern führen kann), stellen wir fest, dass dadurch die Codezeilen reduziert werden und wir eine besser lesbare, wartbare und weniger fehlerhafte Codebasis haben können.

finally

finally wird ausgeführt, egal was passiert, auch wenn eine andere Zeile mit einer return-Anweisung ausgewertet wird.

Mit Pseudocode aufgeschlüsselt

Es kann hilfreich sein, dies in der kleinstmöglichen Form, die alle Funktionen demonstriert, mit Kommentaren aufzuschlüsseln. Angenommen, dieser syntaktisch korrekte (aber nicht ausführbare, wenn die Namen nicht definiert sind) Pseudocode befindet sich in einer Funktion.

Zum Beispiel:

try:
    try_this(whatever)
except SomeException as the_exception:
    handle_SomeException(the_exception)
    # Handle a instance of SomeException or a subclass of it.
except Exception as the_exception:
    generic_handle(the_exception)
    # Handle any other exception that inherits from Exception
    # - doesn't include GeneratorExit, KeyboardInterrupt, SystemExit
    # Avoid bare `except:`
else: # there was no exception whatsoever
    return something()
    # if no exception, the "something()" gets evaluated,
    # but the return will not be executed due to the return in the
    # finally block below.
finally:
    # this block will execute no matter what, even if no exception,
    # after "something" is eval'd but before that value is returned
    # but even if there is an exception.
    # a return here will hijack the return functionality. e.g.:
    return True # hijacks the return in the else clause above

Es ist wahr, dass wir den Code stattdessen in den Block des Blocks aufnehmen könnten , wo er ausgeführt würde, wenn es keine Ausnahmen gäbe, aber was ist, wenn dieser Code selbst eine Ausnahme der Art auslöst, die wir abfangen? Wenn Sie es im Block belassen, wird dieser Fehler ausgeblendet.elsetrytry

Wir möchten die Codezeilen im tryBlock minimieren, um zu vermeiden, dass Ausnahmen abgefangen werden, die wir nicht erwartet haben. Dabei möchten wir, dass unser Code lautstark fehlschlägt, wenn er fehlschlägt. Dies ist eine bewährte Methode .

Nach meinem Verständnis sind Ausnahmen keine Fehler

In Python sind die meisten Ausnahmen Fehler.

Wir können die Ausnahmehierarchie mit pydoc anzeigen. Zum Beispiel in Python 2:

$ python -m pydoc exceptions

oder Python 3:

$ python -m pydoc builtins

Wird uns die Hierarchie geben. Wir können sehen, dass die meisten Arten von ExceptionFehlern sind, obwohl Python einige davon für Dinge wie das Beenden von forSchleifen ( StopIteration) verwendet. Dies ist die Hierarchie von Python 3:

BaseException
    Exception
        ArithmeticError
            FloatingPointError
            OverflowError
            ZeroDivisionError
        AssertionError
        AttributeError
        BufferError
        EOFError
        ImportError
            ModuleNotFoundError
        LookupError
            IndexError
            KeyError
        MemoryError
        NameError
            UnboundLocalError
        OSError
            BlockingIOError
            ChildProcessError
            ConnectionError
                BrokenPipeError
                ConnectionAbortedError
                ConnectionRefusedError
                ConnectionResetError
            FileExistsError
            FileNotFoundError
            InterruptedError
            IsADirectoryError
            NotADirectoryError
            PermissionError
            ProcessLookupError
            TimeoutError
        ReferenceError
        RuntimeError
            NotImplementedError
            RecursionError
        StopAsyncIteration
        StopIteration
        SyntaxError
            IndentationError
                TabError
        SystemError
        TypeError
        ValueError
            UnicodeError
                UnicodeDecodeError
                UnicodeEncodeError
                UnicodeTranslateError
        Warning
            BytesWarning
            DeprecationWarning
            FutureWarning
            ImportWarning
            PendingDeprecationWarning
            ResourceWarning
            RuntimeWarning
            SyntaxWarning
            UnicodeWarning
            UserWarning
    GeneratorExit
    KeyboardInterrupt
    SystemExit

Ein Kommentator fragte:

Angenommen, Sie haben eine Methode, die eine externe API pingt, und Sie möchten die Ausnahme in einer Klasse außerhalb des API-Wrappers behandeln. Geben Sie einfach e von der Methode unter der Ausnahme-Klausel zurück, wobei e das Ausnahmeobjekt ist?

Nein, Sie geben die Ausnahme nicht zurück, sondern erhöhen sie nur mit einem Bare raise, um die Stapelverfolgung beizubehalten .

try:
    try_this(whatever)
except SomeException as the_exception:
    handle(the_exception)
    raise

In Python 3 können Sie auch eine neue Ausnahme auslösen und die Rückverfolgung mit Ausnahmeverkettung beibehalten:

try:
    try_this(whatever)
except SomeException as the_exception:
    handle(the_exception)
    raise DifferentException from the_exception

Ich gehe hier auf meine Antwort ein .

Aaron Hall
quelle
upvoted! Was machst du normalerweise im Griffteil? Angenommen, Sie haben eine Methode, die eine externe API pingt, und Sie möchten die Ausnahme in einer Klasse außerhalb des API-Wrappers behandeln. Geben Sie einfach e von der Methode unter der Ausnahme-Klausel zurück, wobei e das Ausnahmeobjekt ist?
PirateApp
1
@ PirateApp danke! Nein, geben Sie es nicht zurück. Sie sollten es wahrscheinlich mit einer bloßen raiseoder einer Ausnahmeverkettung wiederholen - aber das ist mehr zum Thema und wird hier behandelt: stackoverflow.com/q/2052390/541136 - Ich werde diese Kommentare wahrscheinlich entfernen, nachdem ich gesehen, du hast sie gesehen.
Aaron Hall
Vielen Dank für die Details!
Ich
36

Python schließt sich nicht der Idee an, dass Ausnahmen nur in Ausnahmefällen verwendet werden sollten. Tatsächlich lautet die Redewendung "Bitte um Vergebung, nicht um Erlaubnis" . Dies bedeutet, dass die Verwendung von Ausnahmen als Routineteil Ihrer Flusskontrolle durchaus akzeptabel ist und in der Tat empfohlen wird.

Dies ist im Allgemeinen eine gute Sache, da auf diese Weise einige Probleme vermieden werden (als offensichtliches Beispiel werden häufig die Rennbedingungen vermieden) und der Code dadurch tendenziell besser lesbar wird.

Stellen Sie sich vor, Sie haben eine Benutzereingabe, die verarbeitet werden muss, aber eine Standardeinstellung, die bereits verarbeitet wird. Die try: ... except: ... else: ...Struktur sorgt für sehr gut lesbaren Code:

try:
   raw_value = int(input())
except ValueError:
   value = some_processed_value
else: # no error occured
   value = process_value(raw_value)

Vergleichen Sie, wie es in anderen Sprachen funktionieren könnte:

raw_value = input()
if valid_number(raw_value):
    value = process_value(int(raw_value))
else:
    value = some_processed_value

Beachten Sie die Vorteile. Es ist nicht erforderlich, den Wert zu überprüfen und separat zu analysieren. Sie werden einmal ausgeführt. Der Code folgt auch einer logischeren Abfolge. Der Hauptcodepfad ist zuerst, gefolgt von "Wenn dies nicht funktioniert, tun Sie dies".

Das Beispiel ist natürlich ein wenig erfunden, aber es zeigt, dass es Fälle für diese Struktur gibt.

Gareth Latty
quelle
15

Ist es eine gute Praxis, try-außer-else in Python zu verwenden?

Die Antwort darauf ist, dass es kontextabhängig ist. Wenn du das tust:

d = dict()
try:
    item = d['item']
except KeyError:
    item = 'default'

Es zeigt, dass Sie Python nicht sehr gut kennen. Diese Funktionalität ist in der dict.getMethode gekapselt :

item = d.get('item', 'default')

Der try/ except-Block ist eine viel visuell überladenere und ausführlichere Art zu schreiben, was mit einer atomaren Methode effizient in einer einzelnen Zeile ausgeführt werden kann. Es gibt andere Fälle, in denen dies zutrifft.

Dies bedeutet jedoch nicht, dass wir jede Ausnahmebehandlung vermeiden sollten. In einigen Fällen ist es bevorzugt, Rennbedingungen zu vermeiden. Überprüfen Sie nicht, ob eine Datei vorhanden ist, sondern versuchen Sie einfach, sie zu öffnen und den entsprechenden IOError abzufangen. Versuchen Sie der Einfachheit und Lesbarkeit halber, dies zu kapseln oder als apropos herauszufiltern.

Lesen Sie das Zen von Python und verstehen Sie, dass es Prinzipien gibt, die unter Spannung stehen, und hüten Sie sich vor Dogmen, die sich zu stark auf eine der darin enthaltenen Aussagen stützen.

Aaron Hall
quelle
12

Sehen Sie sich das folgende Beispiel an, das alles über try-außer-else-finally veranschaulicht:

for i in range(3):
    try:
        y = 1 / i
    except ZeroDivisionError:
        print(f"\ti = {i}")
        print("\tError report: ZeroDivisionError")
    else:
        print(f"\ti = {i}")
        print(f"\tNo error report and y equals {y}")
    finally:
        print("Try block is run.")

Implementieren Sie es und kommen Sie vorbei:

    i = 0
    Error report: ZeroDivisionError
Try block is run.
    i = 1
    No error report and y equals 1.0
Try block is run.
    i = 2
    No error report and y equals 0.5
Try block is run.
Infinitesimalrechnung
quelle
3
Dies ist ein großartiges, einfaches Beispiel, das schnell die vollständige try- Klausel demonstriert , ohne dass jemand (der es möglicherweise ziemlich eilig hat) eine ausführliche abstrakte Erklärung lesen muss. (Wenn sie es nicht mehr eilig haben, sollten sie natürlich zurückkommen und das vollständige Abstract lesen.)
GlobalSoftwareSociety
6

Sie sollten vorsichtig sein, wenn Sie den finally-Block verwenden, da dies nicht dasselbe ist wie die Verwendung eines else-Blocks beim Versuch, außer. Der finally-Block wird unabhängig vom Ergebnis des Versuchs ausgeführt, außer.

In [10]: dict_ = {"a": 1}

In [11]: try:
   ....:     dict_["b"]
   ....: except KeyError:
   ....:     pass
   ....: finally:
   ....:     print "something"
   ....:     
something

Wie jeder bemerkt hat, führt die Verwendung des else-Blocks dazu, dass Ihr Code besser lesbar ist und nur ausgeführt wird, wenn keine Ausnahme ausgelöst wird

In [14]: try:
             dict_["b"]
         except KeyError:
             pass
         else:
             print "something"
   ....:
Greg
quelle
Ich weiß, dass schließlich immer ausgeführt wird, und deshalb kann es zu unserem Vorteil genutzt werden, indem immer ein Standardwert festgelegt wird. Im Ausnahmefall wird es zurückgegeben, wenn wir diesen Wert im Ausnahmefall nicht zurückgeben möchten reicht aus, um den letzten Block zu entfernen. Übrigens ist es etwas, was ich niemals tun würde, einen Ausnahmefang zu verwenden :)
Juan Antonio Gomez Moriano
@ Juan Antonio Gomez Moriano, mein Codierungsblock dient nur zum Beispiel. Ich würde wahrscheinlich auch nie Pass verwenden
Greg
4

Wann immer Sie dies sehen:

try:
    y = 1 / x
except ZeroDivisionError:
    pass
else:
    return y

Oder sogar das:

try:
    return 1 / x
except ZeroDivisionError:
    return None

Betrachten Sie stattdessen Folgendes:

import contextlib
with contextlib.suppress(ZeroDivisionError):
    return 1 / x
Rajiv Bakulesh Shah
quelle
1
Es beantwortet meine Frage nicht, da dies nur ein Beispiel für meinen Freund war.
Juan Antonio Gomez Moriano
In Python sind Ausnahmen keine Fehler. Sie sind nicht einmal außergewöhnlich. In Python ist es normal und natürlich, Ausnahmen für die Flusskontrolle zu verwenden. Dies wird durch die Aufnahme von contextlib.suppress () in die Standardbibliothek belegt. Siehe Raymond Hettingers Antwort hier: stackoverflow.com/a/16138864/1197429 (Raymond ist ein zentraler Python-Mitarbeiter und eine Autorität in allen pythonischen Dingen!)
Rajiv Bakulesh Shah
4

Nur weil sonst niemand diese Meinung gepostet hat, würde ich sagen

Vermeiden Sie elseKlauseln, try/excepts da sie den meisten Menschen unbekannt sind

Im Gegensatz zu den Schlüsselwörtern try, exceptund finallydie Bedeutung der elseist Klausel nicht selbstverständlich; es ist weniger lesbar. Da es nicht sehr oft verwendet wird, möchten Benutzer, die Ihren Code lesen, die Dokumente überprüfen, um sicherzustellen, dass sie verstehen, was los ist.

(Ich schreibe diese Antwort genau, weil ich eine try/except/elsein meiner Codebasis gefunden habe und sie einen WTF-Moment verursachte und mich zwang, etwas zu googeln).

Also, wo immer ich Code wie das OP-Beispiel sehe:

try:
    try_this(whatever)
except SomeException as the_exception:
    handle(the_exception)
else:
    # do some more processing in non-exception case
    return something

Ich würde es vorziehen, umzugestalten

try:
    try_this(whatever)
except SomeException as the_exception:
    handle(the_exception)
    return  # <1>
# do some more processing in non-exception case  <2>
return something
  • Die explizite Rückgabe <1> zeigt deutlich, dass wir im Ausnahmefall mit der Arbeit fertig sind

  • <2> Als netter kleiner Nebeneffekt wird der Code, der sich früher im elseBlock befand, um eine Ebene reserviert.

hwjp
quelle
1
Gegenargument des Teufelsarguments: Je mehr Menschen es benutzen, desto besser wird es angenommen. Nur Denkanstöße, obwohl ich der Meinung bin, dass Lesbarkeit wichtig ist. Das heißt, sobald jemand Try-else versteht, würde ich argumentieren, dass es in vielen Fällen viel besser lesbar ist als die Alternative.
Bob
2

Dies ist mein einfacher Ausschnitt darüber, wie man den Try-außer-else-finally-Block in Python versteht:

def div(a, b):
    try:
        a/b
    except ZeroDivisionError:
        print("Zero Division Error detected")
    else:
        print("No Zero Division Error")
    finally:
        print("Finally the division of %d/%d is done" % (a, b))

Versuchen wir es mit div 1/1:

div(1, 1)
No Zero Division Error
Finally the division of 1/1 is done

Versuchen wir es mit div 1/0

div(1, 0)
Zero Division Error detected
Finally the division of 1/0 is done
Zakiakhmad
quelle
1
Ich denke, dies ist kein Beispiel dafür, warum man den else-Code nicht einfach in den Versuch
einfügen kann
-4

OP, SIE SIND RICHTIG. Das andere nach try / außer in Python ist hässlich . es führt zu einem anderen Flusssteuerungsobjekt, für das keines benötigt wird:

try:
    x = blah()
except:
    print "failed at blah()"
else:
    print "just succeeded with blah"

Ein völlig klares Äquivalent ist:

try:
    x = blah()
    print "just succeeded with blah"
except:
    print "failed at blah()"

Dies ist weitaus klarer als eine else-Klausel. Das else nach try / exception wird nicht häufig geschrieben, daher dauert es einen Moment, um die Auswirkungen herauszufinden.

Nur weil Sie etwas tun können, heißt das nicht, dass Sie etwas tun sollten.

Sprachen wurden viele Funktionen hinzugefügt, weil jemand dachte, dass dies nützlich sein könnte. Das Problem ist, je mehr Funktionen, desto weniger klar und offensichtlich sind die Dinge, weil die Leute diese Schnickschnack normalerweise nicht benutzen.

Nur meine 5 Cent hier. Ich muss mitkommen und eine Menge Code bereinigen, der im ersten Jahr von College-Entwicklern geschrieben wurde, die denken, dass sie schlau sind und Code auf eine überaus enge, übereffiziente Art und Weise schreiben wollen, wenn dies nur zu einem Chaos führt um später zu versuchen, zu lesen / zu ändern. Ich stimme jeden Tag und sonntags zweimal für Lesbarkeit.

Kevin J. Rice
quelle
15
Du hast recht. Das ist völlig klar und gleichwertig ... es sei denn, Ihre printAussage schlägt fehl. Was passiert, wenn x = blah()a zurückgegeben strwird, Ihre Druckanweisung jedoch lautet print 'just succeeded with blah. x == %d' % x? Jetzt haben Sie ein TypeErrorWesen erzeugt, in dem Sie nicht bereit sind, mit einem umzugehen. Sie x = blah()suchen nach der Quelle der Ausnahme, und sie ist noch nicht einmal vorhanden. Ich habe dies (oder das Äquivalent) mehr als einmal getan, wo elsemich das davon abgehalten hätte, diesen Fehler zu machen. Jetzt weiß ich es besser. :-D
Doug R.
2
... und ja, du hast recht. Die elseKlausel ist keine schöne Aussage, und bis Sie daran gewöhnt sind, ist sie nicht intuitiv. Aber dann war es auch nicht, finallyals ich anfing, es zu benutzen ...
Doug R.
2
Um Doug R. zu wiederholen, ist es nicht gleichwertig, da Ausnahmen während der Anweisungen in der elseKlausel nicht von der erfasst werden except.
Alastair
Wenn ... außer ... else besser lesbar ist, müssen Sie ansonsten "oh, nach dem try-Block und ohne Ausnahme gehen Sie zu einer Anweisung außerhalb des try-Blocks" lesen. Wenn Sie also else verwenden, wird die Syntax tendenziell ein wenig semantisch verbunden besser imo. Es wird auch empfohlen, Ihre nicht eingefangenen Anweisungen außerhalb des anfänglichen try-Blocks zu belassen.
Cowbert
1
@ DougR. "Sie überprüfen x = blah(), um die Quelle der Ausnahme zu finden". tracebackWarum sollten Sie die Ausnahmequelle von einem falschen Ort aus untersuchen?
Nehem