Soll ich testen if
, ob etwas gültig ist oder nur try
, um es zu tun und die Ausnahme abzufangen?
- Gibt es eine solide Dokumentation, die besagt, dass ein Weg bevorzugt wird?
- Ist ein Weg mehr pythonisch ?
Zum Beispiel sollte ich:
if len(my_list) >= 4:
x = my_list[3]
else:
x = 'NO_ABC'
Oder:
try:
x = my_list[3]
except IndexError:
x = 'NO_ABC'
Einige Gedanken ...
PEP 20 sagt:
Fehler sollten niemals stillschweigend vergehen.
Sofern nicht ausdrücklich zum Schweigen gebracht.
Sollte die Verwendung von a try
anstelle von a if
als stillschweigender Fehler interpretiert werden? Und wenn ja, bringen Sie es explizit zum Schweigen, indem Sie es auf diese Weise verwenden, sodass es in Ordnung ist?
Ich beziehe mich nicht auf Situationen, in denen Sie Dinge nur auf eine Weise tun können. beispielsweise:
try:
import foo
except ImportError:
import baz
if index in mylist
testet, ob der Index ein Element der Mylist ist, kein möglicher Index. Sie würdenif index < len(mylist)
stattdessen wollen .In diesem speziellen Fall sollten Sie etwas ganz anderes verwenden:
Im Allgemeinen jedoch: Wenn Sie erwarten, dass der Test häufig fehlschlägt, verwenden Sie
if
. Wenn der Test teuer ist, wenn Sie nur den Vorgang versuchen und die Ausnahme abfangen, wenn er fehlschlägt, verwenden Sietry
. Wenn keine dieser Bedingungen zutrifft, gehen Sie mit dem, was leichter zu lesen ist.quelle
Die Verwendung
try
undexcept
direkt anstelle einerif
Wache sollte immer erfolgen, wenn die Möglichkeit einer Rennbedingung besteht. Wenn Sie beispielsweise sicherstellen möchten, dass ein Verzeichnis vorhanden ist, gehen Sie nicht wie folgt vor:Wenn ein anderer Thread oder Prozess das Verzeichnis zwischen
isdir
und erstelltmkdir
, werden Sie beendet. Tun Sie stattdessen Folgendes:Das wird nur beendet, wenn das 'foo'-Verzeichnis nicht erstellt werden kann.
quelle
Wenn es trivial ist, zu überprüfen, ob etwas fehlschlägt, bevor Sie es tun, sollten Sie dies wahrscheinlich bevorzugen. Schließlich braucht das Erstellen von Ausnahmen (einschließlich der zugehörigen Rückverfolgungen) Zeit.
Ausnahmen sollten verwendet werden für:
break
Sie nicht weit genug bringt) oder ...Beachten Sie, dass die eigentliche Antwort häufig "weder" lautet. In Ihrem ersten Beispiel sollten Sie beispielsweise nur
.get()
einen Standard angeben:quelle
if 'ABC' in myDict: x = myDict['ABC']; else: x = 'NO_ABC'
ist eigentlich oft schneller als zu benutzenget
, leider. Nicht zu sagen, dass dies das wichtigste Kriterium ist, aber es ist etwas, das man beachten muss.if / else
undtry / except
kann seinen Platz haben, auch wenn es fallspezifische Alternativen gibt, weil sie unterschiedliche Leistungsmerkmale haben..get()
ist die Attribut-Suche und der Overhead für Funktionsaufrufe auf Python-Ebene. Die Verwendung von Schlüsselwörtern für integrierte Funktionen geht im Grunde direkt zu C. Ich glaube nicht, dass es bald zu viel schneller wird. Wasif
vs. betriffttry
, gibt die read dict.get () -Methode einen Zeiger zurück, der einige Leistungsinformationen enthält. Das Verhältnis von Treffern zu Fehlschlägen spielt eine Rolle (try
kann schneller sein, wenn der Schlüssel fast immer vorhanden ist), ebenso wie die Größe des Wörterbuchs.Wie in den anderen Beiträgen erwähnt, hängt es von der Situation ab. Die Verwendung von try / birgt einige Gefahren, außer dass die Gültigkeit Ihrer Daten im Voraus überprüft wird, insbesondere wenn Sie sie in größeren Projekten verwenden.
Angenommen, Sie hatten:
Der IndexError sagt nichts darüber aus, ob er beim Abrufen eines Elements von index_list oder my_list aufgetreten ist.
quelle
Die Verwendung
try
bestätigt, dass ein Fehler auftreten kann, was das Gegenteil davon ist, dass er stillschweigend passiert. Die Verwendungexcept
bewirkt, dass es überhaupt nicht bestanden wird.Die Verwendung
try: except:
wird in Fällen bevorzugt, in denen dieif: else:
Logik komplizierter ist. Einfach ist besser als komplex; komplex ist besser als kompliziert; und es ist einfacher, um Vergebung zu bitten als um Erlaubnis.Was "Fehler niemals stillschweigend passieren sollten" warnt, ist der Fall, in dem Code eine Ausnahme auslösen könnte, über die Sie Bescheid wissen, und in der Ihr Design die Möglichkeit zulässt, Sie aber nicht so entworfen haben, dass Sie mit der Ausnahme umgehen können. Ein Fehler explizit zum Schweigen zu bringen, würde meiner Ansicht nach so etwas wie
pass
in einemexcept
Block tun , was nur mit dem Verständnis geschehen sollte, dass "nichts tun" wirklich die richtige Fehlerbehandlung in der jeweiligen Situation ist. (Dies ist eines der wenigen Male, bei denen ich der Meinung bin, dass ein Kommentar in gut geschriebenem Code wahrscheinlich wirklich benötigt wird.)In Ihrem speziellen Beispiel ist jedoch keines von beiden angemessen:
Der Grund, warum alle darauf hinweisen - obwohl Sie Ihren Wunsch nach allgemeinem Verständnis und die Unfähigkeit, ein besseres Beispiel zu finden, anerkennen -, ist, dass es in vielen Fällen tatsächlich gleichwertige Nebenschritte gibt, und die Suche nach ihnen ist der erster Schritt zur Lösung des Problems.
quelle
try/except
Fragen Sie sich, wann immer Sie den Kontrollfluss verwenden:try
Block erfolgreich ist und wann er fehlschlägt?try
Block?try
Block die Ausnahme auslöst?try
Blocks ändert, verhält sich Ihr Kontrollfluss dann weiterhin wie erwartet?Wenn die Antwort auf eine oder mehrere dieser Fragen "Nein" lautet, muss möglicherweise viel um Vergebung gebeten werden. höchstwahrscheinlich von deinem zukünftigen Selbst.
Ein Beispiel. Ich habe kürzlich Code in einem größeren Projekt gesehen, das so aussah:
Im Gespräch mit dem Programmierer stellte sich heraus, dass der beabsichtigte Kontrollfluss war:
Dies funktionierte, weil
foo
eine Datenbankabfrage durchgeführt wurde und die Abfrage erfolgreich war, wennx
es sich um eine Ganzzahl handelte, und eineProgrammingError
if-x
Liste ausgelöst wurde.Verwenden
try/except
ist hier eine schlechte Wahl:ProgrammingError
verrät nicht das eigentliche Problem (dasx
ist keine Ganzzahl), was es schwierig macht zu sehen, was los ist.ProgrammingError
wird während eines Datenbankaufrufs ausgelöst, was Zeit verschwendet. Es würde wirklich schrecklich werden, wenn sich herausstellen würde, dassfoo
etwas in die Datenbank geschrieben wird, bevor eine Ausnahme ausgelöst wird, oder der Status eines anderen Systems geändert wird.ProgrammingError
nurx
eine Liste von ganzen Zahlen ausgelöst wird. Angenommenfoo
, die Datenbankabfrage enthält einen Tippfehler . Dies könnte auch a auslösenProgrammingError
. Die Folge ist, dassbar(x)
jetzt auch aufgerufen wird, wennx
es sich um eine Ganzzahl handelt. Dies kann zu kryptischen Ausnahmen führen oder zu unvorhersehbaren Ergebnissen führen.try/except
Block fügt allen zukünftigen Implementierungen von eine Anforderung hinzufoo
. Wann immer wir uns ändernfoo
, müssen wir jetzt darüber nachdenken, wie es mit Listen umgeht, und sicherstellen, dass es einenProgrammingError
und beispielsweise keinenAttributeError
oder gar keinen Fehler auslöst.quelle
Für eine allgemeine Bedeutung können Sie Redewendungen und Anti-Redewendungen in Python: Ausnahmen lesen .
In Ihrem speziellen Fall sollten Sie, wie andere angegeben haben, Folgendes verwenden
dict.get()
:quelle