Głównym argumentem tej książki jest to, że wersja wyjątkowa kodu jest lepsza, ponieważ przechwyci wszystko, co można przeoczyć, jeśli spróbujesz napisać własne sprawdzanie błędów.
Myślę, że to stwierdzenie jest prawdziwe tylko w bardzo szczególnych okolicznościach - gdy nie obchodzi cię, czy dane wyjściowe są prawidłowe.
Nie ma wątpliwości, że zgłaszanie wyjątków jest rozsądną i bezpieczną praktyką. Powinieneś to zrobić za każdym razem, gdy czujesz, że jest coś w bieżącym stanie programu, z którym (jako programista) nie możesz lub nie chcesz sobie poradzić.
Twój przykład dotyczy jednak wychwytywania wyjątków. Jeśli złapiesz wyjątek, nie chronisz się przed scenariuszami, które mogłeś przeoczyć. Robisz dokładnie odwrotnie: zakładasz, że nie przeoczyłeś żadnego scenariusza, który mógłby spowodować tego rodzaju wyjątek, i dlatego masz pewność, że można go złapać (a tym samym uniemożliwić wyjście programu, jak każdy niewyłapany wyjątek).
Używając podejścia wyjątkowego, jeśli widzisz ValueError
wyjątek, pomijasz linię. Stosując tradycyjne podejście nie będące wyjątkami, zliczasz liczbę zwróconych wartości split
, a jeśli jest mniejsza niż 2, pomijasz linię. Czy powinieneś czuć się bezpieczniej dzięki podejściu wyjątkowemu, ponieważ mogłeś zapomnieć o innych sytuacjach „błędu” w tradycyjnym sprawdzaniu błędów i except ValueError
złapałbyś je dla siebie?
To zależy od charakteru twojego programu.
Jeśli piszesz na przykład przeglądarkę internetową lub odtwarzacz wideo, problem z danymi wejściowymi nie powinien powodować awarii z niewyłapanym wyjątkiem. O wiele lepiej jest wydać coś sensownie (nawet jeśli, ściśle mówiąc, niepoprawnego), niż wyjść.
Jeśli piszesz aplikację, w której ważna jest poprawność (np. Oprogramowanie biznesowe lub inżynierskie), byłoby to okropne podejście. Jeśli zapomniałeś o jakimś scenariuszu, który wywołuje ValueError
, najgorsze, co możesz zrobić, to po cichu zignorować ten nieznany scenariusz i po prostu pominąć linię. W ten sposób bardzo subtelne i kosztowne błędy kończą się w oprogramowaniu.
Możesz pomyśleć, że jedynym sposobem na zobaczenie ValueError
tego kodu jest split
zwrócenie tylko jednej wartości (zamiast dwóch). Ale co, jeśli twoje print
oświadczenie zacznie później używać wyrażenia, które pojawia się ValueError
w pewnych warunkach? Spowoduje to, że pominiesz niektóre linie nie dlatego, że nie trafiają :
, ale dlatego, że print
zawodzą. To jest przykład subtelnego błędu, o którym wspominałem wcześniej - niczego nie zauważysz, po prostu stracisz kilka linii.
Radzę, aby unikać wychwytywania (ale nie podnoszenia!) Wyjątków w kodzie, w których wytwarzanie niepoprawnych danych wyjściowych jest gorsze niż wychodzenie. Jedyny raz, kiedy wychwytuję wyjątek w takim kodzie, ma naprawdę trywialne wyrażenie, dzięki czemu mogę łatwo zrozumieć, co może powodować każdy z możliwych typów wyjątków.
Jeśli chodzi o wpływ zastosowania wyjątków na wydajność, jest to trywialne (w Pythonie), chyba że często występują wyjątki.
Jeśli używasz wyjątków do obsługi rutynowo występujących warunków, możesz w niektórych przypadkach ponieść ogromne koszty wydajności. Załóżmy na przykład, że zdalnie wykonujesz jakieś polecenie. Możesz sprawdzić, czy tekst polecenia spełnia przynajmniej minimalne wymagania sprawdzania poprawności (np. Składnia). Możesz też poczekać na zgłoszenie wyjątku (co dzieje się dopiero po zdalnym przeanalizowaniu polecenia przez zdalny serwer i znalezieniu problemu). Oczywiście ten pierwszy jest o rząd wielkości szybszy. Kolejny prosty przykład: możesz sprawdzić, czy liczba jest zero ~ 10 razy szybsza niż próba wykonania podziału, a następnie wyłapanie wyjątku ZeroDivisionError.
Te rozważania mają znaczenie tylko wtedy, gdy często wysyłasz zniekształcone ciągi poleceń do zdalnych serwerów lub otrzymujesz argumenty o zerowej wartości, których używasz do dzielenia.
Uwaga: Zakładam, że użyłbyś except ValueError
zamiast sprawiedliwego except
; jak zauważyli inni, i jak sama książka mówi na kilku stronach, nigdy nie powinieneś używać goły except
.
Inna uwaga: właściwym podejściem nie będącym wyjątkiem jest policzenie liczby zwracanych wartości split
zamiast szukania :
. Ten ostatni jest zdecydowanie zbyt wolny, ponieważ powtarza pracę wykonaną przez split
i może prawie podwoić czas wykonania.