Gibt es eine Begründung, um zu entscheiden, welches try
oder welche if
Konstrukte verwendet werden sollen, wenn eine Variable auf einen Wert getestet wird?
Beispielsweise gibt es eine Funktion, die entweder eine Liste oder keinen Wert zurückgibt. Ich möchte das Ergebnis vor der Verarbeitung überprüfen. Welche der folgenden Möglichkeiten wäre vorzuziehen und warum?
result = function();
if (result):
for r in result:
#process items
oder
result = function();
try:
for r in result:
#process items
except TypeError:
pass;
Antworten:
Sie hören oft, dass Python den EAFP- Stil ("es ist einfacher, um Vergebung als um Erlaubnis zu bitten") gegenüber dem LBYL- Stil ("schauen, bevor Sie springen") fördert . Für mich ist es eine Frage der Effizienz und Lesbarkeit.
In Ihrem Beispiel (sagen wir, anstatt eine Liste oder eine leere Zeichenfolge zurückzugeben, sollte die Funktion eine Liste zurückgeben oder
None
) würderesult
ich dentry/except
Ansatz verwenden , wenn Sie erwarten, dass 99% der Zeit tatsächlich etwas Iterierbares enthalten . Es wird schneller sein, wenn Ausnahmen wirklich außergewöhnlich sind. Wennresult
istNone
mehr als 50% der Zeit, dann verwendenif
ist wahrscheinlich besser.Um dies mit ein paar Messungen zu unterstützen:
Während eine
if
Anweisung Sie immer kostet, ist es fast kostenlos, einentry/except
Block einzurichten . Aber wennException
tatsächlich ein auftritt, sind die Kosten viel höher.Moral:
try/except
für die Flusskontrolle zu verwenden.Exception
s tatsächlich außergewöhnlich sind.Aus den Python-Dokumenten:
quelle
try/except
war es 25% schneller alsif key in d:
in Fällen, in denen sich der Schlüssel im Wörterbuch befand. Es war viel langsamer, wenn der Schlüssel nicht wie erwartet im Wörterbuch enthalten war, und stimmte mit dieser Antwort überein.1/1
mit timeit ist keine gute Wahl, da sie optimiert werden (siehedis.dis('1/1')
und beachten Sie, dass keine Unterteilung erfolgt).Ihre Funktion sollte keine gemischten Typen zurückgeben (dh Liste oder leere Zeichenfolge). Es sollte eine Liste von Werten oder nur eine leere Liste zurückgeben. Dann müssten Sie nicht auf irgendetwas testen, dh Ihr Code kollabiert zu:
quelle
Bitte ignorieren Sie meine Lösung, wenn der von mir bereitgestellte Code auf den ersten Blick nicht offensichtlich ist und Sie die Erklärung nach dem Codebeispiel lesen müssen.
Kann ich davon ausgehen, dass "kein Wert zurückgegeben" bedeutet, dass der Rückgabewert "Keine" ist? Wenn ja oder wenn der "Nein-Wert" boolesch falsch ist, können Sie Folgendes tun, da Ihr Code "Kein Wert" im Wesentlichen als "Nicht iterieren" behandelt:
Wenn
function()
etwas zurückgegeben wird, das nicht wahr ist, iterieren Sie über das leere Tupel, dh Sie führen keine Iterationen aus. Dies ist im Wesentlichen LBYL.quelle
Ihr zweites Beispiel ist fehlerhaft - der Code löst niemals eine TypeError-Ausnahme aus, da Sie sowohl Zeichenfolgen als auch Listen durchlaufen können. Das Durchlaufen einer leeren Zeichenfolge oder Liste ist ebenfalls gültig - es wird der Hauptteil der Schleife nullmal ausgeführt.
quelle
Look Before You Leap ist in diesem Fall vorzuziehen. Mit dem Ausnahmeansatz kann ein TypeError an einer beliebigen Stelle in Ihrem Schleifenkörper auftreten und abgefangen und weggeworfen werden. Dies ist nicht das, was Sie möchten, und macht das Debuggen schwierig.
(Ich stimme jedoch Brandon Corfman zu: Die Rückgabe von None für 'no items' anstelle einer leeren Liste ist fehlerhaft. Es ist eine unangenehme Angewohnheit von Java-Codierern, die in Python nicht zu sehen ist. Oder Java.)
quelle
Im Allgemeinen habe ich den Eindruck, dass Ausnahmen außergewöhnlichen Umständen vorbehalten sein sollten. Wenn
result
erwartet wird, dass die Festplatte niemals leer ist (dies kann jedoch der Fall sein, wenn beispielsweise eine Festplatte abstürzt usw.), ist der zweite Ansatz sinnvoll. Wenn andererseits einresult
Leerzeichen unter normalen Bedingungen durchaus sinnvoll ist , ist es sinnvoller, es mit einerif
Aussage zu testen .Ich dachte an das (häufigere) Szenario:
anstelle des Äquivalents:
quelle
++
Verwenden Sie+= 1
stattdessen nur eine kurze Notiz, die in Python nicht funktioniert .bobince weist weise darauf hin, dass das Umschließen des zweiten Falls auch TypeErrors in der Schleife abfangen kann, was nicht das ist, was Sie wollen. Wenn Sie wirklich einen Versuch verwenden möchten, können Sie vor der Schleife testen, ob er iterierbar ist
Wie Sie sehen können, ist es ziemlich hässlich. Ich schlage es nicht vor, aber es sollte der Vollständigkeit halber erwähnt werden.
quelle
None
überprüfen Sie das Ergebnis immer mitis None
oderis not None
. Auf der anderen Seite ist es auch ein schlechter Stil, Ausnahmen für legitime Ergebnisse zu erheben. Ausnahmen sind für die unerwarteten Dinge. Beispiel:str.find()
Gibt -1 zurück, wenn nichts gefunden wird, da die Suche selbst fehlerfrei abgeschlossen wurde.In Bezug auf die Leistung ist die Verwendung des try-Blocks für Code, der normalerweise keine Ausnahmen auslöst, schneller als die Verwendung der if-Anweisung jedes Mal. Die Entscheidung hängt also von der Wahrscheinlichkeit von Ausnahmefällen ab.
quelle
Als allgemeine Faustregel sollten Sie niemals try / catch oder andere Ausnahmebehandlungsmittel verwenden, um den Fluss zu steuern. Auch wenn die Iteration hinter den Kulissen über das Auslösen von
StopIteration
Ausnahmen gesteuert wird , sollten Sie Ihr erstes Code-Snippet dem zweiten vorziehen.quelle