In и index в списке [Python]

Я пытаюсь понять внутреннюю работу команды in и index() структуры данных списка.

Когда я говорю:

if something not in some_list :
    print "do something"

Перебирает ли он весь список внутри, подобно циклу for или использует его, лучше подходит, например, hashtables и т.д.

Также в index() в списках появляется сообщение об ошибке, если элемент отсутствует в списке. Является ли работа как in, так и index() одинаковой? Если index() лучше, то возможно ли поймать ошибку, когда элемент отсутствует, и если это возможно, это хорошее программирование?

Ответ 1

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

Если вы знаете о "Big O" нотации, структура данных list предназначена для доступа O (1) путем поиска известного индекса, например. my_list[13]. Это O (n) для тестирования членства.

Существуют другие структуры данных, оптимизированные для скорости O (1) для тестирования членства (т.е. __contains__), а именно set и dict. Они реализованы с помощью hashtables.

Вот пример того, как вы можете использовать IPython, чтобы проверить временную сложность наборы и списки, чтобы подтвердить эти претензии:

In [1]: short_list, long_list = range(1000), range(10000)

In [2]: timeit 'potato' not in short_list
10000 loops, best of 3: 40.9 µs per loop

In [3]: timeit 'potato' not in long_list
1000 loops, best of 3: 440 µs per loop

In [4]: small_set, big_set = set(short_list), set(long_list)

In [5]: timeit 'potato' not in small_set
10000000 loops, best of 3: 72.9 ns per loop

In [6]: timeit 'potato' not in big_set
10000000 loops, best of 3: 84.5 ns per loop

Ответ 2

Для списков, оба метода (in и index()) повторяют по списку, чтобы проверить, какой элемент вы ищете, к сожалению. Они остановят итерацию, как только будет получен результат теста на членство, что означает, что они будут итерации до конца, если элемент не найден.

Насколько мне известно, если вы должны работать со списками, конструкцией not in является самый Python и тот, с которым вы должны пойти (но вы должны сбросить ненужные круглые скобки).

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

Да, вы можете планировать время, когда элемент, который вы проверяете, отсутствует в вашей структуре данных. Вы ищете Try/Except Block:

example_list = [1,2,3]

try:
     index_of_4 = example_list.index(4)
except ValueError:
     print("Oops! 4 wasn't in the list!")

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