Suche…


Übereifrig mit Ausnahme der Klausel

Ausnahmen sind mächtig, aber eine einzige übereifrige Ausnahme-Klausel kann alles in einer einzigen Zeile wegnehmen.

try:
    res = get_result()
    res = res[0]
    log('got result: %r' % res)
except:
    if not res:
        res = ''
    print('got exception')

Dieses Beispiel zeigt 3 Symptome des Antipattern:

  1. Die except ohne Ausnahmetyp (Zeile 5) fängt sogar fehlerhafte Ausnahmen auf, einschließlich KeyboardInterrupt . Dadurch wird das Programm in einigen Fällen möglicherweise nicht beendet.
  2. Der Ausnahme-Block erhöht den Fehler nicht erneut, was bedeutet, dass wir nicht feststellen können, ob die Ausnahme innerhalb von get_result oder weil res eine leere Liste war.
  3. Am schlimmsten: Wenn wir uns Sorgen machten, dass das Ergebnis leer wäre, haben wir etwas Schlimmeres verursacht. Wenn get_result fehlschlägt, bleibt res vollständig unset und der Verweis auf res im außer -Block NameError , dass NameError und der ursprüngliche Fehler vollständig maskiert wird.

Denken Sie immer an die Art der Ausnahme, mit der Sie umgehen möchten. Lesen Sie die Ausnahmeseite und erfahren Sie, welche grundlegenden Ausnahmen bestehen.

Hier ist eine feste Version des obigen Beispiels:

import traceback

try:
    res = get_result()
except Exception: 
    log_exception(traceback.format_exc())
    raise
try:
    res = res[0]
except IndexError:
    res = ''

log('got result: %r' % res)

Wir stellen spezifischere Ausnahmen fest und reraisen wenn nötig. Ein paar Zeilen mehr, aber unendlich viel korrekter.

Schauen Sie, bevor Sie mit einer prozessorintensiven Funktion springen

Ein Programm kann leicht Zeit verschwenden, indem eine prozessorintensive Funktion mehrmals aufgerufen wird.

Nehmen wir zum Beispiel eine Funktion , die wie folgt aussieht: es eine ganze Zahl zurück , wenn der value ein, sonst produzieren kann None :

def intensive_f(value): # int -> Optional[int]
   # complex, and time-consuming code
   if process_has_failed:
       return None
   return integer_output

Und es könnte auf folgende Weise verwendet werden:

x = 5
if intensive_f(x) is not None:
    print(intensive_f(x) / 2)
else:
    print(x, "could not be processed")

print(x)

Während dies funktioniert, hat es das Problem, intensive_f aufzurufen, wodurch sich die Zeitdauer für die Ausführung des Codes verdoppelt. Eine bessere Lösung wäre, den Rückgabewert der Funktion vorher zu erhalten.

x = 5
result = intensive_f(x)
if result is not None:
    print(result / 2)
else:
    print(x, "could not be processed")

Ein klarer und möglicherweise pythonischerer Weg ist jedoch die Verwendung von Ausnahmen, zum Beispiel:

x = 5
try:
    print(intensive_f(x) / 2)
except TypeError: # The exception raised if None + 1 is attempted
    print(x, "could not be processed")

Hier wird keine temporäre Variable benötigt. Es kann oft vorzuziehen sein, eine assert Anweisung zu verwenden und stattdessen AssertionError abzufangen.

Wörterbuchschlüssel

Ein häufiges Beispiel dafür ist der Zugriff auf Wörterbuchschlüssel. Zum Beispiel vergleichen Sie:

bird_speeds = get_very_long_dictionary()

if "european swallow" in bird_speeds:
    speed = bird_speeds["european swallow"]
else:
    speed = input("What is the air-speed velocity of an unladen swallow?")

print(speed)

mit:

bird_speeds = get_very_long_dictionary()

try:
    speed = bird_speeds["european swallow"]
except KeyError:
    speed = input("What is the air-speed velocity of an unladen swallow?")

print(speed)

Im ersten Beispiel muss das Wörterbuch zweimal durchgesehen werden. Da es sich um ein langes Wörterbuch handelt, kann dies jedes Mal sehr lange dauern. Die zweite erfordert nur eine Suche durch das Wörterbuch und spart somit viel Prozessorzeit.

Eine Alternative dazu ist die Verwendung von dict.get(key, default) . In vielen Fällen können jedoch komplexere Vorgänge erforderlich sein, wenn der Schlüssel nicht vorhanden ist



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow