Подтвердить что ты не робот

Лучше ли использовать исключение или код возврата в Python?

Вы можете знать эту рекомендацию от Microsoft об использовании исключений в .NET:

Оценка производительности

...

Выбросить исключения только для чрезвычайные условия,...

Кроме того, не бросайте исключение когда код возврата достаточен...

(см. весь текст http://msdn.microsoft.com/en-us/library/system.exception.aspx.)

Как точка сравнения, вы бы порекомендовали то же самое для кода Python?

4b9b3361

Ответ 1

Пифонов нужно делать, чтобы поднимать и обрабатывать исключения. Отличная книга "Python в двух словах" обсуждает это в "Стратегии проверки ошибок" в главе 6.

В книге обсуждается EAFP ( "проще просить прощения, чем разрешение" ) по сравнению с LBYL ( "посмотрите, прежде чем прыгать" ).

Итак, чтобы ответить на ваш вопрос:

Нет, я бы не рекомендовал то же самое для кода python. Я предлагаю вам прочитать главу 6 Python в двух словах.

Ответ 2

Лучший способ понять исключения - " если ваш метод не может сделать то, что говорит его имя, бросьте." Мое личное мнение состоит в том, что этот совет должен применяться одинаково как для .NET, так и для Python.

Основное различие заключается в том, что у вас есть методы, которые часто не могут выполнять то, что их имя говорит, что они должны делать, например, анализировать строки как целые числа или извлекать запись из базы данных. Стиль С# заключается в том, чтобы избежать исключения в первую очередь:

int i;
if (Int32.TryParse(myString, out i)) {
    doWhatever(i);
}
else {
    doWhatever(0);
}

в то время как Python гораздо удобнее в этом:

try:
    i = int(myString)
except ValueError:
    i = 0
doWhatever(i);

Ответ 3

В исключениях Python не так дорого, как на некоторых других языках, поэтому я бы не рекомендовал избегать исключений. Но если вы делаете исключение, вы обычно захотите поймать его где-нибудь в своем коде, исключение будет, если произойдет фатальная ошибка.

Ответ 4

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

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

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

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

Ответ 5

Я сделал простой эксперимент, чтобы сравнить производительность по сбору исключений со следующим кодом:

from functools import wraps
from time import time
import logging

def timed(foo):
    @wraps(foo)
    def bar(*a, **kw):
        s = time()
        foo(*a, **kw)
        e = time()
        print '%f sec' % (e - s)
    return bar

class SomeException(Exception):
    pass

def somefunc(_raise=False):
    if _raise:
        raise SomeException()
    else:
        return

@timed
def test1(_reps):
    for i in xrange(_reps):
        try:
            somefunc(True)
        except SomeException:
            pass

@timed
def test2(_reps):
    for i in xrange(_reps):
        somefunc(False)

def main():

    test1(1000000)
    test2(1000000)

    pass

if __name__ == '__main__':
    main()

Со следующими результатами:

  • Исключение исключений: 3.142000 sec
  • Использование return: 0.383000 сек

Исключения примерно в 8 раз медленнее, чем при использовании return.

Ответ 6

Я думаю, что вернуть код ошибки или выбросить исключение - это что-то очень действительное, о чем можно подумать, и кросс-лингвистическое сравнение может быть полезным и информативным. Я думаю, что очень обобщенный ответ на эту озабоченность - это просто рассмотрение: набор допустимых значений возврата для любой функции должен быть сделан как можно меньше и насколько это необходимо.

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

Возвращаемое значение наименьшего сюрприза обычно None; и если вы посмотрите на него, вы увидите, что его семантика None, которая лицензирует его использование по всем направлениям: это одноэлементное неизменяемое значение, которое во многих случаях оценивается как False или запрещает дальнейшие вычисления -не конкатенации, без арифметики. Поэтому, если вы решили написать метод frob(x), который возвращает число для ввода строки, и None для нечисловых строк и любого другого ввода, и вы используете это внутри выражения типа a=42+frob('foo'), вы все равно получаете исключение очень близко к точке, в которой произошло фиктивное действие. Конечно, если вы введете frob('foo') в столбец базы данных, который не был определен с помощью NOT NULL, вы можете столкнуться с проблемами, возможно, через несколько месяцев. Это может быть или не быть оправданным.

Поэтому в большинстве случаев, когда вы, например, хотите вывести число из строки, используя что-то вроде bare float(x) или int(x), это путь, так как эти встроенные модули будут создавать исключение, если не заданы усредняемые данные. Если это не подходит для вашего использования, подумайте о возврате None из пользовательского метода; в основном, это возвращаемое значение говорит потребителям, что "Извините, я не смог понять ваш вклад. Но вы только хотите это сделать, если вы положительно знаете, что в вашей программе есть смысл с этой точки зрения и далее.

Видите ли, я только что узнал, как превратить каждое уведомление, предупреждение и сообщение об ошибке в потенциально исключение show-stopping в, м, PHP. Это просто сводит меня с ума, что опечатка в имени переменной генерируется в стандартной конфигурации PHP, ничего, кроме уведомления пользователя. Это , поэтому плохо. Программа просто продолжает делать что-то с программным кодом, который не имеет смысла вообще! Я не могу поверить, что люди находят эту особенность.

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

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