Использование try vs if в python
49921 просмотра
9 ответа
Есть ли обоснование, чтобы решить, какой из try
или if
конструкции использовать при тестировании переменной, чтобы иметь значение?
Например, есть функция, которая возвращает список или не возвращает значение. Я хочу проверить результат перед его обработкой. Что из следующего будет более предпочтительным и почему?
result = function();
if (result):
for r in result:
#process items
или же
result = function();
try:
for r in result:
#process items
except TypeError:
pass;
Связанное обсуждение:
Проверка существования члена в Python
Автор: artdanil Источник Размещён: 12.11.2019 09:07Ответы (9)
204 плюса
Вы часто слышите, что Python поддерживает стиль EAFP («проще просить прощения, чем разрешения») над стилем LBYL («смотри, прежде чем прыгнуть»). Для меня это вопрос эффективности и читабельности.
В вашем примере (скажем, что вместо того, чтобы возвращать список или пустую строку, функция должна была возвращать список или None
), если вы ожидаете, что 99% времени result
будет содержать что-то итеративное, я бы использовал try/except
подход. Это будет быстрее, если исключения действительно являются исключительными. Если result
это None
более 50% времени, то, if
вероятно, лучше использовать.
Чтобы поддержать это с помощью нескольких измерений:
>>> import timeit
>>> timeit.timeit(setup="a=1;b=1", stmt="a/b") # no error checking
0.06379691968322732
>>> timeit.timeit(setup="a=1;b=1", stmt="try:\n a/b\nexcept ZeroDivisionError:\n pass")
0.0829463709378615
>>> timeit.timeit(setup="a=1;b=0", stmt="try:\n a/b\nexcept ZeroDivisionError:\n pass")
0.5070195056614466
>>> timeit.timeit(setup="a=1;b=1", stmt="if b!=0:\n a/b")
0.11940114974277094
>>> timeit.timeit(setup="a=1;b=0", stmt="if b!=0:\n a/b")
0.051202772912802175
Таким образом, в то время как if
утверждение всегда стоит вас, установить try/except
блок практически бесплатно . Но когда это Exception
действительно происходит, стоимость намного выше.
Мораль:
- Это нормально (и "питоническое") использовать
try/except
для управления потоком, - но это имеет смысл больше всего, когда
Exception
s на самом деле исключительны.
Из документов Python:
Автор: Tim Pietzcker Размещён: 02.12.2009 09:10ЭСПЦ
Проще просить прощения, чем разрешения. Этот общий стиль кодирования Python предполагает наличие допустимых ключей или атрибутов и перехватывает исключения, если предположение оказывается ложным. Это чистый и быстрый стиль характеризуется наличием многих
try
иexcept
заявлений. Техника контрастирует со стилем LBYL, общим для многих других языков, таких как C.
13 плюса
Ваша функция не должна возвращать смешанные типы (то есть список или пустую строку). Он должен возвращать список значений или просто пустой список. Тогда вам не нужно будет ничего проверять, то есть ваш код сворачивается в:
for r in function():
# process items
Автор: Brandon
Размещён: 02.12.2009 09:11
10 плюса
Пожалуйста, игнорируйте мое решение, если код, который я предоставляю, на первый взгляд неочевиден, и вы должны прочитать объяснение после примера кода.
Могу ли я предположить, что «значение не возвращено» означает, что возвращаемое значение равно None? Если да, или если «no value» - False в логическом смысле, вы можете сделать следующее, так как ваш код по существу обрабатывает «no value» как «not iterate»:
for r in function() or ():
# process items
Если function()
возвращает что-то, что не соответствует действительности, вы перебираете пустой кортеж, то есть вы не запускаете никаких итераций. Это по сути LBYL.
5 плюса
Ваш второй пример не работает - код никогда не сгенерирует исключение TypeError, поскольку вы можете перебирать как строки, так и списки. Итерация по пустой строке или списку также допустима - она выполнит тело цикла ноль раз.
Автор: Dave Kirby Размещён: 02.12.2009 09:074 плюса
Что из следующего будет более предпочтительным и почему?
Смотри, прежде чем прыгать предпочтительнее в этом случае. При исключительном подходе ошибка TypeError может возникнуть в любом месте тела цикла, и она может быть захвачена и выброшена, а это не то, что вам нужно, и затруднит отладку.
(Однако я согласен с Брэндоном Корфманом: возвращение None для 'no items' вместо пустого списка не работает. Это неприятная привычка Java-кодеров, которую не следует видеть в Python. Или Java.)
Автор: bobince Размещён: 02.12.2009 10:394 плюса
Как правило, у меня сложилось впечатление, что исключения должны быть зарезервированы для исключительных обстоятельств. Если result
ожидается, что он никогда не будет пустым (но может быть, например, в случае сбоя диска и т. Д.), Второй подход имеет смысл. Если, с другой стороны, пустое result
является вполне разумным в нормальных условиях, проверка на это с помощью if
утверждения имеет больше смысла.
Я имел в виду (более распространенный) сценарий:
# keep access counts for different files
file_counts={}
...
# got a filename somehow
if filename not in file_counts:
file_counts[filename]=0
file_counts[filename]+=1
вместо эквивалента:
...
try:
file_counts[filename]+=1
except KeyError:
file_counts[filename]=1
Автор: Managu
Размещён: 02.12.2009 09:09
3 плюса
bobince мудро указывает на то, что перенос второго регистра также может перехватывать TypeErrors в цикле, а это не то, что вам нужно. Если вы действительно хотите использовать попытку, вы можете проверить, повторяется ли она перед циклом
result = function();
try:
it = iter(result)
except TypeError:
pass
else:
for r in it:
#process items
Как видите, это довольно некрасиво. Я не предлагаю это, но это должно быть упомянуто для полноты.
Автор: AFoglia Размещён: 03.12.2009 06:211 плюс
Что касается производительности, то использование блока try для кода, который обычно не вызывает исключений, быстрее, чем использование оператора if каждый раз. Итак, решение зависит от вероятности исключительных случаев.
Автор: grayger Размещён: 03.12.2009 02:33-5 плюса
Как общее практическое правило, вы никогда не должны использовать try / catch или другие средства обработки исключений для управления потоком. Несмотря на то, что закулисная итерация контролируется с помощью возбуждения StopIteration
исключений, вы все равно должны предпочесть свой первый фрагмент кода второму.
Вопросы из категории :
- python Обработка XML в Python
- python Как я могу использовать Python itertools.groupby ()?
- python Python: На какой ОС я работаю?
- python Как я могу создать непосредственно исполняемое кроссплатформенное приложение с графическим интерфейсом на Python?
- python Вызов функции модуля с использованием его имени (строки)
- python Звук Питона («Колокол»)
- python Regex и unicode
- python Создать зашифрованный ZIP-файл в Python
- python Создайте базовый итератор Python
- python Функция транспонирования / распаковки (обратная сторона zip)?
- python Каков наилучший способ разбора аргументов командной строки?
- python Формат чисел в строки в Python
- python Как загрузить файл через HTTP с помощью Python?
- python Is there any difference between "foo is None" and "foo == None"?
- python Как запустить сценарий Python как службу в Windows?
- python Нахождение каких методов у объекта Python
- python Как отсортировать список строк?
- python Что ** (двойная звезда / звездочка) и * (звездочка / звездочка) делают для параметров?
- python What is the purpose of class methods?
- python Какой лучший способ вернуть несколько значений из функции в Python?