Избегать исключений? - PullRequest
       24

Избегать исключений?

8 голосов
/ 03 января 2009

Этот конкретный пример относится к Django в Python, но должен применяться к любому языку, поддерживающему исключения:

try:
    object = ModelClass.objects.get(search=value)
except DoesNotExist:
    pass

if object:
    # do stuff

Класс модели Django предоставляет простой метод get , который позволяет мне искать один и только один объект из базы данных, если он находит более или менее, он вызывает исключение. Если можно найти ноль или более с помощью альтернативного метода filter , который возвращает список:

objects = ModelClass.objects.filter(search=value)
if len(objects) == 1:
    object = objects[0]
    # do stuff

Не слишком ли я склонен к исключениям? Мне кажется, что исключение выглядит немного расточительным, по-видимому, четверть с половиной времени будет «исключительной». Я бы предпочел функцию, которая возвращает Нет при сбое. Буду ли я лучше использовать метод filter Django и обработать список самостоятельно?

Ответы [ 7 ]

9 голосов
/ 04 января 2009

Верьте или нет, но на самом деле это проблема, которая немного отличается в каждом языке. В Python исключения регулярно генерируются для событий, которые не являются исключительными для самого языка. Таким образом, я думаю, что правило «вы должны бросать исключения только в исключительных обстоятельствах» не совсем применимо. Я думаю, что результаты, которые вы получите на этом форуме, будут отклонены от этой точки зрения, учитывая большое количество программистов .Net (см. этот вопрос ) для получения дополнительной информации об этом).

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

7 голосов
/ 03 января 2009

Существует большой раскол в языках программирования вокруг использования исключений.

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

  • Существует мнение сильного меньшинства, что исключения - это просто еще одна конструкция потока управления, и они должны быть дешевыми. Standard ML из Нью-Джерси и Objective Caml компиляторы подписываются под этим мнением. Если у вас есть дешевые исключения, вы можете закодировать некоторые причудливые алгоритмы обратного отслеживания способами, которые сложнее кодировать аккуратно с использованием других механизмов.

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

5 голосов
/ 03 января 2009

Подсказка в названии - исключения должны быть исключительными.

Если вы всегда ожидаете, что элемент будет существовать, тогда используйте get, но если вы ожидаете, что он не будет существовать в течение разумного промежутка времени (т.е. он не существует, является ожидаемым результатом, а не исключительным результатом), тогда я бы предложить использовать filter.

Итак, учитывая, что вы указали, что от 1 к 2 и от 1 к 4, как ожидается, не существует, я бы определенно написал обертку вокруг filter, поскольку это определенно не исключительный случай.

2 голосов
/ 04 января 2009

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

Вот более реалистичный пример использования Django с базой данных sqlite в памяти. Был выполнен каждый из 100 различных запросов, а затем усреднен для каждого из 100 запусков. Хотя я сомневаюсь, что это будет иметь значение, я также изменил порядок исполнения.

With ObjectDoesNotExist... 0.102783939838
Without exception ........ 0.105322141647

With ObjectDoesNotExist... 0.102762134075
Without exception ........ 0.101523952484

With ObjectDoesNotExist... 0.100004930496
Without exception ........ 0.107946784496

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

2 голосов
/ 03 января 2009

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

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

2 голосов
/ 03 января 2009

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


Edit:

В ответ на запрос об этом я запустил этот простой тест ...

import time

def timethis(func, list, num):
  st=time.time()
  for i in xrange(0,1000000):
    try:
      func(list,num)
    except:
      pass
  et = time.time()
  print "Took %gs" % (et-st)

def check(list, num):
  if num < len(list):
    return list[num]
  else:
    return None

a=[1]
timethis(check, a, 1)
timethis(lambda x,y:x[y], a, 1)

И вывод был ..

Took 0.772558s
Took 3.4512s

НТН.

2 голосов
/ 03 января 2009

Ответ будет зависеть от цели кода. (Я не уверен, для чего предназначался ваш пример кода, передача в исключительном случае сбивает с толку, что будет делать остальная часть кода с переменной object для работы?)

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...