Как проверить, есть ли что-то (нет) в списке в Python?
Самое дешевое и удобочитаемое решение - использование in
оператора (или в вашем конкретном случае not in
). Как указано в документации,
Операторы in
и not in
тест на членство. x in s
оценивается,
True
если x
является членом s
, и в False
противном случае. x not in s
возвращает отрицание x in s
.
Дополнительно,
Оператор not in
определен, чтобы иметь обратное истинное значение in
.
y not in x
логически так же, как not y in x
.
Вот несколько примеров:
'a' in [1, 2, 3]
# False
'c' in ['a', 'b', 'c']
# True
'a' not in [1, 2, 3]
# True
'c' not in ['a', 'b', 'c']
# False
Это также работает с кортежами, так как кортежи являются хэшируемыми (вследствие того, что они также являются неизменяемыми):
(1, 2) in [(3, 4), (1, 2)]
# True
Если объект в RHS определяет __contains__()
метод, он in
будет внутренне вызывать его, как указано в последнем абзаце раздела « Сравнения » документации.
... in
и not in
поддерживаются типами, которые являются итеративными или реализуют
__contains__()
метод. Например, вы можете (но не должны) сделать это:
[3, 2, 1].__contains__(1)
# True
in
короткие замыкания, поэтому, если ваш элемент находится в начале списка, in
вычисляется быстрее:
lst = list(range(10001))
%timeit 1 in lst
%timeit 10000 in lst # Expected to take longer time.
68.9 ns ± 0.613 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
178 µs ± 5.01 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
Если вы хотите сделать больше, чем просто проверить, есть ли элемент в списке, есть варианты:
list.index
может быть использован для получения индекса элемента. Если этот элемент не существует, a ValueError
повышается.
list.count
может быть использован, если вы хотите подсчитать вхождения.
Проблема XY: Вы рассматривали set
с?
Задайте себе эти вопросы:
- Вам нужно проверить, есть ли элемент в списке более одного раза?
- Эта проверка выполняется внутри цикла или функция вызывается повторно?
- Элементы, которые вы храните в своем списке, можно изменить? IOW, вы можете позвонить
hash
им?
Если вы ответили «да» на эти вопросы, вы должны использовать set
вместо этого. Проверка in
членства на list
s - это O (n) сложность времени. Это означает, что python должен выполнить линейное сканирование вашего списка, посещая каждый элемент и сравнивая его с элементом поиска. Если вы делаете это неоднократно или если списки велики, эта операция повлечет за собой дополнительные затраты.
set
объекты, с другой стороны, хэшируют свои значения для проверки членства в постоянное время. Проверка также выполняется с использованием in
:
1 in {1, 2, 3}
# True
'a' not in {'a', 'b', 'c'}
# False
(1, 2) in {('a', 'c'), (1, 2)}
# True
Если вам не повезло, что элемент, который вы ищете / не ищете, находится в конце вашего списка, python просканирует список до конца. Это видно из времени ниже:
l = list(range(100001))
s = set(l)
%timeit 100000 in l
%timeit 100000 in s
2.58 ms ± 58.9 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
101 ns ± 9.53 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
Напоминаем, что это подходящий вариант, если элементы, которые вы храните и просматриваете, являются хэшируемыми. Таким образом, они должны быть неизменяемыми типами или объектами, которые реализуют __hash__
.
3 -1 > 0 and (4-1 , 5) not in []
⤇True
поэтому ошибка не является одним из приоритетов операторов.