Должен ли я проверить if
что-то действительно или просто try
сделать это и поймать исключение?
- Есть ли надежная документация о том, что предпочтителен один из способов?
- Является ли один способ более питоническим ?
Например, я должен:
if len(my_list) >= 4:
x = my_list[3]
else:
x = 'NO_ABC'
Или:
try:
x = my_list[3]
except IndexError:
x = 'NO_ABC'
Некоторые мысли ...
20 человек говорит:
Ошибки никогда не должны проходить бесшумно.
Если явно не молчать.
Следует ли использовать try
вместо вместо if
интерпретировать ошибку, как молчание? И если так, вы явно заставляете его замолчать, используя его таким образом, поэтому делаете это нормально?
Я не имею в виду ситуации, когда вы можете делать вещи только в одном направлении; например:
try:
import foo
except ImportError:
import baz
if index in mylist
Индекс тестов является элементом mylist, а не возможным индексом. Вы бы хотелиif index < len(mylist)
вместо этого.if/else
чемtry/catch
В этом конкретном случае вы должны использовать что-то еще полностью:
В общем, хотя: если вы ожидаете, что тест не пройдёт часто, используйте
if
. Если тест стоит дорого по сравнению с простой попыткой операции и перехватом исключения, если оно не выполнено, используйтеtry
. Если ни одно из этих условий не применимо, делайте все, что читается легче.источник
Использование
try
иexcept
непосредственно, а не внутриif
охраны всегда должно быть сделано, если есть какая-либо возможность состояния гонки. Например, если вы хотите убедиться, что каталог существует, не делайте этого:Если другой поток или процесс создает каталог между
isdir
иmkdir
, вы выйдете. Вместо этого сделайте это:Это завершится, только если каталог 'foo' не может быть создан.
источник
Если до того, как вы это сделаете, проверить, не произойдет ли что-нибудь, тривиально, вы, вероятно, должны это одобрить. В конце концов, создание исключений (включая связанные с ними трассировки) занимает много времени.
Исключения следует использовать для:
break
вы не достаточно далеко) или ...Обратите внимание, что часто реальным ответом является «ни один» - например, в вашем первом примере, что вы действительно должны сделать, это просто использовать
.get()
для обеспечения значения по умолчанию:источник
if 'ABC' in myDict: x = myDict['ABC']; else: x = 'NO_ABC'
это на самом деле часто быстрее, чем использоватьget
, к сожалению. Не сказать, что это самый важный критерий, но это то, что нужно знать.if / else
иtry / except
может иметь место даже тогда , когда есть альтернативы по каждому конкретному случаю , поскольку они имеют разные характеристики..get()
- это поиск атрибутов и служебные вызовы функций на уровне Python; использование ключевых слов во встроенных модулях в основном подходит к C. Я не думаю, что в ближайшее время это станет слишком быстрым. Что касаетсяif
vs.try
, метод read dict.get () возвращает указатель с некоторой информацией о производительности. Соотношение попаданий и промахов имеет значение (try
может быть быстрее, если ключ почти всегда существует), так же как и размер словаря.Как упоминают другие посты, это зависит от ситуации. Есть несколько опасностей с использованием try /, за исключением того, что вы заранее проверяете достоверность ваших данных, особенно при использовании их в больших проектах.
например, предположим, что вы имели:
IndexError ничего не говорит о том, произошло ли это при попытке получить элемент index_list или my_list.
источник
Использование
try
- это подтверждение того, что ошибка может пройти, что противоположно тому, чтобы она прошла без предупреждения. Использованиеexcept
заставляет его не проходить вообще.Использование
try: except:
предпочтительнее в тех случаях, когдаif: else:
логика более сложна. Простое лучше, чем сложное; комплекс лучше, чем сложный; и проще просить прощения, чем разрешения.То, что «ошибки никогда не должны проходить молча», является предупреждением, это случай, когда код может вызвать исключение, о котором вы знаете, и где ваш дизайн допускает такую возможность, но вы не спроектировали таким образом, чтобы иметь дело с этим исключением. Явное глушителей ошибку, на мой взгляд, будет делать что - то подобное
pass
вexcept
блоке, который должен быть сделан только с пониманием того, что «ничего не делать» на самом деле являются правильной обработка ошибок в конкретной ситуации. (Это один из немногих случаев, когда мне кажется, что комментарий в хорошо написанном коде действительно необходим).Однако в вашем конкретном примере ни один из них не подходит:
Причина, по которой все указывают на это - даже если вы признаете свое желание понять в целом и неспособность придумать лучший пример - в том, что эквивалентные побочные шаги действительно существуют во многих случаях, и поиск их является Первый шаг в решении проблемы.
источник
Всякий раз, когда вы используете
try/except
для управления потоком, спросите себя:try
блок успешен, а когда нет?try
блока?try
блок выдает исключение?try
блока изменится, будет ли ваш поток управления работать так, как ожидалось?Если ответом на один или несколько из этих вопросов является «нет», может потребоваться много прощения; скорее всего от твоего будущего я.
Пример. Недавно я увидел код в более крупном проекте, который выглядел так:
В разговоре с программистом выяснилось, что предполагаемый поток управления:
Это сработало, потому что
foo
сделал запрос к базе данных, и запрос был бы успешным, если быx
был целым числом, и бросил бы,ProgrammingError
если быx
был список.Использование
try/except
- плохой выбор здесь:ProgrammingError
не выдает фактическую проблему (котораяx
не является целым числом), что затрудняет понимание того, что происходит.ProgrammingError
Поднят во время вызова базы данных, которая время отходы. Все было бы по-настоящему ужасно, если бы выяснилось, чтоfoo
что- то записывает в базу данных до того, как произойдет исключение, или изменит состояние какой-либо другой системы.ProgrammingError
возникает ли он только тогда, когдаx
это список целых чисел. Предположим, например, что вfoo
запросе к базе данных есть опечатка . Это также может поднятьProgrammingError
. Следствием является то, чтоbar(x)
теперь также называется, когдаx
является целым числом. Это может вызвать загадочные исключения или привести к непредсказуемым результатам.try/except
Блок добавляет требование для всех реализаций будущихfoo
. Всякий раз, когда мы меняемсяfoo
, мы должны теперь думать о том, как он обрабатывает списки, и быть уверенным, что он выдает ошибку,ProgrammingError
а не, скажем,AttributeError
ошибку или нет вообще.источник
Для общего значения, вы можете рассмотреть чтение идиом и анти-идиом в Python: исключения .
В вашем конкретном случае, как говорили другие, вы должны использовать
dict.get()
:источник