Используя попытку, по сравнению с если в Python

Полезный для парсинга аргументов хранимой процедуры: xp_sscanf

Считывает данные со строки в местоположения аргумента, определенные каждым аргументом формата.

следующий пример использует xp_sscanf для извлечения двух значений из исходной строки на основе их положений в формате исходной строки.

DECLARE @filename varchar (20), @message varchar (20)
EXEC xp_sscanf 'sync -b -fproducts10.tmp -rrandom', 'sync -b -f%s -r%s', 
  @filename OUTPUT, @message OUTPUT
SELECT @filename, @message

Вот набор результатов.

-------------------- -------------------- 
products10.tmp        random

120
задан Community 23 May 2017 в 10:31
поделиться

9 ответов

Вы часто слышите, что Python поощряет стиль EAFP («проще просить прощения, чем разрешения»), а не стиль LBYL («посмотрите перед собой прыжок"). Для меня это вопрос эффективности и удобочитаемости.

В вашем примере (скажем, что вместо возврата списка или пустой строки функция должна была возвращать список или None ), если вы ожидаете что в 99% случаев result будет фактически содержать что-то повторяемое, я бы использовал подход try / except . Будет быстрее, если исключения действительно будут исключительными. Если результат равен Нет более чем в 50% случаев, то, вероятно, лучше использовать , если .

Чтобы подтвердить это с помощью нескольких измерений:

>>> 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 always стоит вам, можно почти бесплатно настроить блок try / except . Но когда действительно возникает исключение , стоимость намного выше.

Мораль:

  • Совершенно нормально (и "питонически") использовать try / except для управления потоком ,
  • но это имеет смысл, когда Exception на самом деле являются исключительными.

Из документов Python:

EAFP

Проще просить прощения, чем

  • , но это имеет смысл больше всего, когда Exception на самом деле являются исключительными.
  • Из документов Python:

    EAFP

    Проще просить прощения, чем

  • , но это имеет смысл больше всего, когда Exception на самом деле являются исключительными.
  • Из документов Python:

    EAFP

    Проще просить прощения, чем разрешение. Эта общая кодировка Python стиль предполагает наличие действительных ключи или атрибуты и уловки исключения, если предположение подтверждается ложный. Этот чистый и быстрый стиль характеризуется наличием множества попробуйте и кроме операторов . В техника контрастирует с LBYL стиль, общий для многих других языков например C.

    207
    ответ дан 24 November 2019 в 01:38
    поделиться

    Ваша функция не должна возвращать смешанные типы (например, список или пустую строку). Он должен возвращать список значений или просто пустой список. Тогда вам не нужно будет ничего тестировать, то есть ваш код сворачивается до:

    for r in function():
        # process items
    
    13
    ответ дан 24 November 2019 в 01:38
    поделиться

    Ваш второй пример неверен - код никогда не вызовет исключение TypeError, поскольку вы можете выполнять итерацию как по строкам, так и по спискам. Итерация по пустой строке или списку также допустима - тело цикла будет выполнено ноль раз.

    4
    ответ дан 24 November 2019 в 01:38
    поделиться

    Пожалуйста, игнорируйте мое решение, если предоставленный мной код неочевиден на первый взгляд, и вы должны прочитать объяснение после примера кода.

    Могу ли я предположить, что «значение не возвращено» означает, что возвращаемое значение - None? Если да, или если «нет значения» имеет значение «Ложь» логическим образом, вы можете сделать следующее, поскольку ваш код по существу обрабатывает «нет значения» как «не повторять»:

    for r in function() or ():
        # process items
    

    If function () возвращает то, что не соответствует действительности, вы перебираете пустой кортеж, т. е. не выполняете никаких итераций. По сути, это LBYL.

    11
    ответ дан 24 November 2019 в 01:38
    поделиться

    Что из следующего было бы более предпочтительным и почему?

    В этом случае предпочтительнее «Посмотрите, прежде чем прыгать». При исключительном подходе ошибка TypeError может произойти где угодно в теле цикла, и ее поймают и выбросят, что не является тем, что вы хотите, и усложнит отладку.

    (Я согласен с Брэндоном Корфманом: возвращение None для "без элементов" вместо пустого списка нарушается. Это неприятная привычка кодеров Java, которую не следует видеть в Python. или Java.)

    4
    ответ дан 24 November 2019 в 01:38
    поделиться

    В общем, у меня сложилось впечатление, что исключения должны быть зарезервированы для исключительных обстоятельств. Если ожидается, что результат никогда не будет пустым (но может быть, например, в случае поломки диска и т. Д.), Второй подход имеет смысл. Если, с другой стороны, пустой результат вполне разумен в нормальных условиях, проверка его с помощью оператора if имеет больше смысла.

    Я имел в виду (more общий) сценарий:

    # 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
    
    4
    ответ дан 24 November 2019 в 01:38
    поделиться

    Что касается производительности, использование блока try для кода, который обычно не вызывает исключения быстрее, чем использование оператора if каждый раз. Итак, решение зависит от вероятности исключительных случаев.

    1
    ответ дан 24 November 2019 в 01:38
    поделиться

    Как правило, вы не должны никогда использовать try / catch или какие-либо средства обработки исключений для управления потоком. Несмотря на то, что итерация «за кулисами» управляется путем создания исключений StopIteration ,

    -5
    ответ дан 24 November 2019 в 01:38
    поделиться

    bobince wisely points out that wrapping the second case can also catch TypeErrors in the loop, which is not what you want. If you do really want to use a try though, you can test if it's iterable before the loop

    result = function();
    try:
        it = iter(result)
    except TypeError:
        pass
    else:
        for r in it:
            #process items
    

    As you can see, it's rather ugly. I don't suggest it, but it should be mentioned for completeness.

    3
    ответ дан 24 November 2019 в 01:38
    поделиться
    Другие вопросы по тегам:

    Похожие вопросы: