Como verifico se algo está (não) em uma lista no Python?
A solução mais barata e legível é usar o in
operador (ou no seu caso específico not in
). Conforme mencionado na documentação,
Os operadores in
e not in
teste para associação. x in s
avalia
True
se x
é um membro s
e de False
outra forma. x not in s
retorna a negação de x in s
.
Além disso,
O operador not in
está definido para ter o valor verdadeiro inverso de in
.
y not in x
é logicamente o mesmo que not y in x
.
Aqui estão alguns exemplos:
'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
Isso também funciona com tuplas, uma vez que as tuplas são hashable (como conseqüência do fato de serem imutáveis):
(1, 2) in [(3, 4), (1, 2)]
# True
Se o objeto no RHS definir um __contains__()
método, ele in
será chamado internamente, conforme observado no último parágrafo da seção Comparações dos documentos.
... in
e not in
são suportados por tipos que são iteráveis ou implementam o
__contains__()
método. Por exemplo, você poderia (mas não deveria) fazer isso:
[3, 2, 1].__contains__(1)
# True
in
curto-circuito, portanto, se o seu elemento estiver no início da lista, in
avalie mais rapidamente:
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)
Se você deseja fazer mais do que apenas verificar se um item está em uma lista, existem opções:
list.index
pode ser usado para recuperar o índice de um item. Se esse elemento não existir, a ValueError
é gerado.
list.count
pode ser usado se você quiser contar as ocorrências.
O problema XY: você já considerou set
s?
Faça a si mesmo estas perguntas:
- você precisa verificar se um item está em uma lista mais de uma vez?
- Essa verificação é feita dentro de um loop ou uma função é chamada repetidamente?
- Os itens que você está armazenando na sua lista são laváveis? IOW, você pode chamá
hash
-los?
Se você respondeu "sim" a essas perguntas, deve usar um set
. Um in
teste de associação em list
s é O (n) complexidade de tempo. Isso significa que o python precisa fazer uma varredura linear da sua lista, visitando cada elemento e comparando-o com o item de pesquisa. Se você estiver fazendo isso repetidamente, ou se as listas forem grandes, essa operação acarretará uma sobrecarga.
set
objetos, por outro lado, hash seus valores para verificação de associação em tempo constante. A verificação também é feita usando in
:
1 in {1, 2, 3}
# True
'a' not in {'a', 'b', 'c'}
# False
(1, 2) in {('a', 'c'), (1, 2)}
# True
Se você é infeliz o suficiente para que o elemento que você está procurando / não esteja no final da sua lista, o python terá escaneado a lista até o final. Isso é evidente nos horários abaixo:
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)
Lembre-se de que essa é uma opção adequada, desde que os elementos que você está armazenando e procurando sejam laváveis. IOW, eles teriam que ser tipos imutáveis ou objetos implementados __hash__
.
3 -1 > 0 and (4-1 , 5) not in []
⤇True
, portanto, o erro não é um dos precedência do operador.