Python list.index выдает исключение, если индекс не найден

Почему list.index генерирует исключение вместо использования произвольного значения (например, -1)? Какова идея этого?

Для меня это выглядит более чистым, чтобы иметь дело со специальными значениями, а не с исключениями.

EDIT: я не понял, что -1 - потенциально допустимое значение. Тем не менее, почему не что-то еще? Как насчет значения None?

Ответы

Ответ 1

Потому что -1 сам по себе является допустимым индексом. Он мог бы использовать другое значение, например None, но это не было бы полезно, что -1 может быть в других ситуациях (таким образом, str.find()), и будет просто проверять ошибки, что и есть то, что исключения для.

Ответ 2

Чтобы добавить к ответу Девина: это старая дискуссия между специальными значениями возврата и исключениями. Многие гуру по программированию предпочитают исключение, потому что при исключении я могу увидеть всю стеклу и немедленно указать, что не так.

Ответ 3

Ну, специальное значение действительно должно быть None, потому что -1 является допустимым индексом (что означает последний элемент списка).

Вы можете эмулировать это поведение:

idx = l.index(x) if x in l else None

Ответ 4

Обсуждение "исключение-vs-error value" частично связано с ясностью кода. Рассмотрим код со значением ошибки:

idx = sequence.index(x)
if idx == ERROR:
    # do error processing
else:
    print '%s occurred at position %s.' % (x, idx)

Обработка ошибок заканчивается заполненной в середине нашего алгоритма, затеняя поток программы. С другой стороны:

try:
    idx = sequence.index(x)
    print '%s occurred at position %s.' % (x, idx)
except IndexError:
    # do error processing

В этом случае количество кода фактически одинаково, но основной алгоритм не прерывается обработкой ошибок.

Ответ 5

В Python -1 является допустимым индексом, означающим число из конца списка (вместо начала), поэтому, если вы должны были сделать

idx = mylist.index(someval)
nextval = mylist[idx+1]

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

if someval in mylist:
    idx = mylist.index(someval)

Изменить: на самом деле нет никакой точки в возврате None, потому что если вы собираетесь тестировать None, вы можете также проверить, находится ли значение в списке, как указано выше!

Ответ 6

В основном это означает, что ошибки будут обнаружены как можно скорее. Например, рассмотрим следующее:

l = [1, 2, 3]
x = l.index("foo")  #normally, this will raise an error
l[x]  #However, if line 2 returned None, it would error here

Вы заметите, что ошибка будет сброшена в l[x], а не в x = l.index("foo"), если индекс должен был вернуть None. В этом примере это не очень важно. Но представьте себе, что третья строка находится в каком-то совершенно другом месте в программе с миллионами строк. Это может привести к некоторому кошмару отладки.

Ответ 7

Я согласен с Devin Jeanpierre и добавлю, что обработка особых значений может показаться хорошей в небольших примерах, но (с несколькими заметными исключениями, например NaN в FPU и Null в SQL), она не масштабируется почти так же хорошо. Единственный раз, когда он работает, - где:

  • Обычно у вас много вложенной однородной обработки (например, математика или SQL).
  • Вам не нужно различать типы ошибок
  • Вам все равно, где произошла ошибка.
  • Операции - это чистые функции без побочных эффектов.
  • Отказ может дать разумный смысл на более высоком уровне (например, "Нет совпадающих строк" )

Ответ 8

Одна простая идея: -1 отлично используется как индекс (как и другие отрицательные значения).

Ответ 9

Это семантический аргумент. Если вы хотите узнать индекс элемента, вы утверждаете, что он уже существует в списке. Если вы хотите узнать, существует ли он, вы должны использовать in.

Ответ 10

def GetListIndex(list, searchString):
    try:
        return list.index(searchString)

    except ValueError:
        return False

    except Exception:
        raise