Лучший способ обращаться с list.index (не мог бы существовать) у питона?

У меня есть кодекс, который выглядит примерно так:

thing_index = thing_list.index(thing)
otherfunction(thing_list, thing_index)

хорошо, таким образом, это упрощено, но Вы получаете идею. Теперь thing не мог бы на самом деле быть в списке, в этом случае я хочу пройти-1 как thing_index. На других языках это - то, что Вы ожидали бы index() возвратиться, если это не могло бы найти элемент. На самом деле это бросает a ValueError.

Я мог сделать это:

try:
    thing_index = thing_list.index(thing)
except ValueError:
    thing_index = -1
otherfunction(thing_list, thing_index)

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

thing_index = ( [(i for i in xrange(len(thing_list)) if thing_list[i]==thing)] or [-1] )[0]

Есть ли более чистый способ достигнуть того же самого? Давайте предположим, что список не сортирован.

95
задан Tim Pietzcker 25 January 2010 в 14:24
поделиться

7 ответов

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

В отличие от Python всегда использовали исключения, чтобы указать нормальный поток программы, как повышение ValueError , как мы обсуждаем здесь. В стиле Python нет ничего "грязного" в стиле Python, и там еще много, где это произошло. Еще более распространенным примером является замедленность , который поднимается методом ITERATOR .

3
ответ дан 24 November 2019 в 05:52
поделиться

В этом документе он буквально называется вопросительным знаком « (включена в дефис) ( http://www.ietf.org/rfc/rfc2396.txt - Прокрутите до 3,2 полномочия компонента).

Я согласен, это плохое имя. Хеш (#) называется идентификатором фрагмента (прокрутите вниз до 4.1). Так что, возможно, его следует назвать идентификатором запроса ».

-121--1728972-
thing_index = thing_list.index(elem) if elem in thing_list else -1

одна строка. Простой. Без исключений.

48
ответ дан 24 November 2019 в 05:52
поделиться

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

thing_index = next((i for i, x in enumerate(thing_list) if x == thing), -1)
5
ответ дан 24 November 2019 в 05:52
поделиться

Нет ничего «грязного» с использованием предложения TRY-BELE. Это питон путь. ValueError будет поднят только методом .index .index .] Поскольку это единственный код, который у вас там!

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

59
ответ дан 24 November 2019 в 05:52
поделиться

Тип dict имеет функцию get, где если ключ не существует в словаре, то 2-й аргумент к get - это значение, которое он должен вернуть. Аналогично существует setdefault, который возвращает значение в dict, если ключ существует, в противном случае он устанавливает значение в соответствии с вашим параметром по умолчанию, а затем возвращает ваш параметр по умолчанию.

Вы можете расширить тип list, чтобы использовать метод getindexdefault.

class SuperDuperList(list):
    def getindexdefault(self, elem, default):
        try:
            thing_index = self.index(elem)
            return thing_index
        except ValueError:
            return default

Который затем можно было бы использовать как:

mylist = SuperDuperList([0,1,2])
index = mylist.getindexdefault( 'asdf', -1 )
15
ответ дан 24 November 2019 в 05:52
поделиться

Как насчет этого:

otherfunction(thing_collection, thing)

, а не разоблачить что-то, что зависит от реализации, как индекс списка в интерфейсе функций, передайте коллекцию и то, что другие, и пусть другие проблемы с вопросами «Тест на членство». Если прочесть записывается, чтобы быть коллекцией - тип агностики, то, вероятно, начнутся с:

if thing in thing_collection:
    ... proceed with operation on thing

, который будет работать, если Thing_Collection - это список, кортеж, набор или Dict.

Это, возможно, более четко, чем:

if thing_index != MAGIC_VALUE_INDICATING_NOT_A_MEMBER:

, который является кодом, который вы уже имеете в другой.

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

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

thing_index = thing_list.index(elem) if thing_list.count(elem) else -1

, но я бы посоветовал против этого; Я думаю, что решение ROSS ROGERS является лучшим, используйте объект для инкапсуляции вашего поведения Desiderd, не пытайся отталкивать язык на его ограничения на стоимость читабельности.

-2
ответ дан 24 November 2019 в 05:52
поделиться
Другие вопросы по тегам:

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