Основний аргумент книги полягає в тому, що версія для винятків коду є кращою, оскільки вона захопить все, що ви могли б не помітити, якби спробували написати власну перевірку помилок.
Я думаю, що це твердження справедливо лише в дуже конкретних обставинах - там, де вам не байдуже, чи правильний результат.
Немає сумнівів, що підвищення винятків є надійною та безпечною практикою. Ви повинні робити це кожного разу, коли відчуєте, що в поточному стані програми є щось, з чим ви (як розробник) не можете чи не хочете мати справу.
Ваш приклад, однак, про ловлі виключення. Якщо ви спіймаєте виняток, ви не захищаєте себе від сценаріїв, які, можливо, ви не помітили. Ви робите саме навпаки: ви припускаєте, що ви не пропустили жодного сценарію, який міг би спричинити виняток такого типу, і тому ви впевнені, що добре його зловити (і тим самим запобігти тому, щоб програма вийшла з програми, як би будь-який неприхований виняток).
Використовуючи підхід виключення, якщо ви бачите ValueError
виняток, ви пропускаєте рядок. Використовуючи традиційний підхід, який не є винятком, ви підраховуєте кількість повернених значень split
, і якщо це менше 2, ви пропускаєте рядок. Якщо ви відчуваєте себе більш захищеними від підходу до винятку, оскільки, можливо, ви забули деякі інші "помилкові" ситуації у вашій традиційній перевірці помилок, і ви except ValueError
захопили б їх для вас?
Це залежить від характеру вашої програми.
Якщо ви пишете, наприклад, веб-браузер або відеоплеєр, проблема з входами не повинна спричиняти збій, за винятком невловимого винятку. Набагато краще вивести щось чутливо віддалене (навіть якщо, строго кажучи, неправильне), ніж кинути.
Якщо ви пишете заявку, де важлива коректність (наприклад, бізнес або інженерне програмне забезпечення), це був би жахливий підхід. Якщо ви забули про якийсь сценарій, який виникає ValueError
, найгірше, що ви можете зробити - це мовчки ігнорувати цей невідомий сценарій і просто пропустити лінію. Ось як дуже тонкі та дорогі помилки виявляються в програмному забезпеченні.
Ви можете подумати, що єдиний спосіб, який ви бачите ValueError
в цьому коді, - це split
повернути лише одне значення (замість двох). Але що робити, якщо print
згодом у вашій заяві почнеться вираз, який виникає ValueError
за певних умов? Це призведе до того, що ви пропустите деякі рядки не тому, що вони пропускають :
, а тому, що print
на них не вдається. Це приклад тонкої помилки, про яку я згадував раніше - ви нічого не помітили, просто втратите кілька рядків.
Моя рекомендація полягає у тому, щоб уникнути (але не підвищувати!) Винятків у коді, коли отримання неправильного результату гірше, ніж вихід. Єдиний раз, коли я вловлю виняток у такому коді - це, коли у мене справді тривіальне вираження, тому я можу легко пояснити, що може спричинити кожен із можливих типів виключень.
Що стосується впливу на ефективність використання винятків, то це тривіально (у Python), якщо винятки не зустрічаються часто.
Якщо ви використовуєте винятки для обробки умов, що виникають у звичайному режимі, ви можете в деяких випадках заплатити величезні витрати на продуктивність. Наприклад, припустимо, ви віддалено виконуєте якусь команду. Ви можете перевірити, чи текст вашої команди проходить принаймні мінімальне підтвердження (наприклад, синтаксис). Або ви можете зачекати, коли буде винято виняток (що відбувається лише після того, як віддалений сервер проаналізує вашу команду та знайде з цим проблему). Очевидно, колишній набирає порядку на швидкість. Ще один простий приклад: ви можете перевірити, чи число дорівнює нулю ~ 10 разів швидше, ніж намагатися виконати ділення, а потім перехопити виняток ZeroDivisionError.
Ці міркування мають значення лише в тому випадку, якщо ви часто надсилаєте неправильно сформовані рядки команд на віддалені сервери або отримуєте аргументи з нульовим значенням, які використовуєте для поділу.
Примітка: я припускаю, що ви б використовували except ValueError
замість справедливого except
; як зазначали інші, і як говориться в самій книзі на кількох сторінках, ви ніколи не повинні використовувати голі except
.
Ще одне зауваження: правильний підхід, що не стосується виключення, - це підрахунок кількості повернених значень split
, а не пошук :
. Останнє є надто повільним, оскільки повторює виконану роботу split
і може майже подвоїти час виконання.