Основной аргумент книги заключается в том, что исключительная версия кода лучше, потому что она поймает все, что вы могли упустить из виду, если попытались написать свою собственную проверку ошибок.
Я думаю, что это утверждение верно только в очень специфических обстоятельствах - где вам все равно, если вывод правильный.
Нет сомнений в том, что поднятие исключений является надежной и безопасной практикой. Вы должны делать это всякий раз, когда чувствуете, что в текущем состоянии программы есть что-то, с чем вы (как разработчик) не можете или не хотите иметь дело.
Ваш пример, однако, о ловле исключений. Если вы поймаете исключение, вы не защитите себя от сценариев, которые вы могли упустить из виду. Вы делаете с точностью до наоборот: вы предполагаете, что вы не пропустили ни одного сценария, который мог бы вызвать исключение такого типа, и поэтому вы уверены, что его можно перехватить (и, таким образом, не дать программе выйти из программы, как и любое необъяснимое исключение).
Используя подход исключения, если вы видите ValueError
исключение, вы пропускаете строку. Используя традиционный подход без исключений, вы подсчитываете количество возвращаемых значений split
, а если оно меньше 2, вы пропускаете строку. Должны ли вы чувствовать себя более защищенно с подходом исключения, так как вы могли забыть о некоторых других ситуациях "ошибки" в своей традиционной проверке ошибок, и except ValueError
поймали бы их для вас?
Это зависит от характера вашей программы.
Если вы пишете, например, веб-браузер или видеоплеер, проблема со входами не должна приводить к его аварийному завершению с неперехваченным исключением. Гораздо лучше вывести что-то отдаленно разумное (даже если, строго говоря, неправильно), чем выйти.
Если вы пишете приложение, в котором важна корректность (например, деловое или инженерное программное обеспечение), это будет ужасный подход. Если вы забыли о каком-то сценарии, который возникает ValueError
, худшее, что вы можете сделать, это молча проигнорировать этот неизвестный сценарий и просто пропустить строку. Вот как очень тонкие и дорогостоящие ошибки заканчиваются в программном обеспечении.
Вы можете подумать, что единственный способ, которым вы можете видеть ValueError
в этом коде, - это split
возвращать только одно значение (вместо двух). Но что, если ваше print
утверждение позже начнет использовать выражение, которое возникает ValueError
при некоторых условиях? Это заставит вас пропустить некоторые строки не потому, что они пропустили :
, а потому, что print
на них не получилось . Это пример тонкой ошибки, о которой я говорил ранее - вы ничего не заметите, просто потеряете несколько строк.
Я рекомендую избегать перехвата (но не возбуждения!) Исключений в коде, где неправильный вывод хуже, чем выход. Единственный раз, когда я ловлю исключение в таком коде, это когда у меня действительно тривиальное выражение, поэтому я легко могу понять, что может вызывать каждый из возможных типов исключений.
Что касается влияния использования исключений на производительность, то оно тривиально (в Python), если исключения не встречаются часто.
Если вы используете исключения для обработки обычно возникающих условий, в некоторых случаях вы можете заплатить огромные затраты производительности. Например, предположим, что вы дистанционно выполняете какую-то команду. Вы можете проверить, что текст вашей команды проходит, по крайней мере, минимальную проверку (например, синтаксис). Или вы можете подождать, пока возникнет исключение (что происходит только после того, как удаленный сервер проанализирует вашу команду и обнаружит с ней проблему). Очевидно, что первый на несколько порядков быстрее. Другой простой пример: вы можете проверить, является ли число нулем ~ в 10 раз быстрее, чем пытаться выполнить деление, а затем перехватить исключение ZeroDivisionError.
Эти соображения имеют значение только в том случае, если вы часто отправляете искаженные строки команд на удаленные серверы или получаете аргументы с нулевым значением, которые вы используете для деления.
Примечание: я полагаю, вы бы использовали except ValueError
вместо просто except
; как указывали другие, и как сказано в самой книге на нескольких страницах, вы никогда не должны использовать голые except
.
Еще одно примечание: правильный подход без исключения заключается в подсчете количества возвращаемых значений split
, а не в поиске :
. Последний слишком медленный, поскольку повторяет выполненную работу split
и может почти удвоить время выполнения.