2010-03-26 14 views
47

W another question, zaakceptowana odpowiedź zasugerowała zastąpienie (bardzo taniej) instrukcji if w kodzie Pythona blokiem try/except w celu poprawienia wydajności.Koszt obsługi wyjątków w Pythonie

Pomijając problemy z stylem kodowania i zakładając, że wyjątek nigdy nie zostanie uruchomiony, jaka jest różnica (pod względem wydajności) od obsługi wyjątku, w przeciwieństwie do braku jednego, w przeciwieństwie do porównywania do zera, jeśli- komunikat?

+6

Kiedy to zmierzyłeś, czego się nauczyłeś? –

+1

Powiązane pytanie: http://stackoverflow.com/questions/1835756/ – tzot

+0

Użyj opcji try/except, chyba że szanse na to, że nastąpi kontrola, z wyjątkiem części, są mniejsze i jeśli/else, jeśli szanse są większe. – shadow0359

Odpowiedz

67

Dlaczego nie zmierzyć go za pomocą ? W ten sposób możesz sprawdzić, czy jest on odpowiedni dla twojej aplikacji.

OK, więc ja tylko próbowałem następujące:

import timeit 

statements=["""\ 
try: 
    b = 10/a 
except ZeroDivisionError: 
    pass""", 
"""\ 
if a: 
    b = 10/a""", 
"b = 10/a"] 

for a in (1,0): 
    for s in statements: 
     t = timeit.Timer(stmt=s, setup='a={}'.format(a)) 
     print("a = {}\n{}".format(a,s)) 
     print("%.2f usec/pass\n" % (1000000 * t.timeit(number=100000)/100000)) 

Wynik:

a = 1 
try: 
    b = 10/a 
except ZeroDivisionError: 
    pass 
0.25 usec/pass 

a = 1 
if a: 
    b = 10/a 
0.29 usec/pass 

a = 1 
b = 10/a 
0.22 usec/pass 

a = 0 
try: 
    b = 10/a 
except ZeroDivisionError: 
    pass 
0.57 usec/pass 

a = 0 
if a: 
    b = 10/a 
0.04 usec/pass 

a = 0 
b = 10/a 
ZeroDivisionError: int division or modulo by zero 

Tak, jak oczekiwano, nie mając żadnej obsługi wyjątku jest nieco szybciej (ale wysadza w swojej twarz, gdy wystąpi wyjątek) i try/except jest szybszy niż jawny if, o ile warunek nie jest spełniony.

Ale wszystko to w tym samym rzędzie wielkości i nie ma to znaczenia w żaden sposób. Tylko wtedy, gdy warunek jest rzeczywiście spełniony, wersja if jest znacznie szybsza.

+1

Interesujące. Więc 'try/except' jest szybszy niż' if a! = 0' – Thilo

+0

@Thilo: Proszę nie pytać. Wykonaj kolejny pomiar i opublikuj wyniki. –

+13

@ S. Lott: Co masz na myśli? Nie pytał, złożył oświadczenie. Jednak zmieniłem swój kod z 'if a! = 0:' na 'if a:' po tym, jak napisał swój komentarz (a przy okazji, to nie miało wpływu na wydajność). Być może to jest powodem nieporozumienia? –

33

To pytanie jest właściwie odpowiedzieć w Design and History FAQ:

spróbuj/z wyjątkiem bloku jest bardzo skuteczne, jeśli nie ma wyjątków są podniesione. Rzeczywiście złapanie wyjątku jest drogie.

+2

Właśnie się zastanawiałem, jak wydajna jest "wyjątkowo skuteczna". Wygląda na to, że jest to szybsze niż bardzo proste stwierdzenie "jeśli". – Thilo

+0

Fragment, który wysłałeś, znajduje się w [Najczęściej zadawanych pytaniach dotyczących historii i projektowania] (http://docs.python.org/faq/design.html). – nitsas

9

To pytanie jest mylące. Jeśli założysz, że wyjątek to nigdy nie jest, żaden z nich nie jest optymalnym kodem.

Jeśli założysz, że wyjątek jest wyzwalany jako część warunku błędu, jesteś już poza obszarem, w którym chcesz uzyskać optymalny kod (a prawdopodobnie i tak nie będziesz go obsługiwał na tak drobnym poziomie).

Jeśli używasz wyjątku jako części standardowego przepływu sterowania - który jest pythonowym sposobem "poprosić o wybaczenie, a nie pozwolenie" - nastąpi uruchomienie wyjątku, a koszt zależy od rodzaju wyjątku, rodzaj, jeśli i jaki procent czasu oszacowania wyjątek się dzieje.

Powiązane problemy