¿Cómo verifico si algo está (no) en una lista en Python?
La solución más barata y más legible es usar el in
operador (o en su caso específico not in
). Como se menciona en la documentación,
Los operadores in
y not in
prueba de membresía. x in s
evalúa
True
si x
es miembro de s
, y de lo False
contrario. x not in s
devuelve la negación de x in s
.
Adicionalmente,
El operador not in
se define para tener el valor verdadero inverso de in
.
y not in x
es lógicamente lo mismo que not y in x
.
Aquí están algunos ejemplos:
'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
Esto también funciona con las tuplas, ya que las tuplas son hashable (como consecuencia del hecho de que también son inmutables):
(1, 2) in [(3, 4), (1, 2)]
# True
Si el objeto en el RHS define un __contains__()
método, in
lo llamará internamente, como se señala en el último párrafo de la sección de Comparaciones de los documentos.
... in
y not in
son compatibles con tipos que son iterables o implementan el
__contains__()
método. Por ejemplo, podría (pero no debería) hacer esto:
[3, 2, 1].__contains__(1)
# True
in
cortocircuitos, por lo que si su elemento está al principio de la lista, in
evalúa más rápido:
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)
Si desea hacer más que simplemente verificar si un elemento está en una lista, hay opciones:
list.index
se puede usar para recuperar el índice de un artículo. Si ese elemento no existe, ValueError
se genera a.
list.count
puede usarse si desea contar las ocurrencias.
El problema XY: ¿Has considerado set
s?
Hágase estas preguntas:
- ¿necesita verificar si un artículo está en una lista más de una vez?
- ¿Se realiza esta comprobación dentro de un bucle o se llama repetidamente a una función?
- ¿Los elementos que está almacenando en su lista son hashable? IOW, ¿puedes llamarlos
hash
?
Si respondió "sí" a estas preguntas, debería utilizar un set
en su lugar. Una in
prueba de membresía en list
s es O (n) complejidad de tiempo. Esto significa que Python tiene que hacer un escaneo lineal de su lista, visitando cada elemento y comparándolo con el elemento de búsqueda. Si está haciendo esto repetidamente, o si las listas son grandes, esta operación generará una sobrecarga.
set
Los objetos, por otro lado, calculan sus valores para la verificación de membresía de tiempo constante. La verificación también se realiza utilizando in
:
1 in {1, 2, 3}
# True
'a' not in {'a', 'b', 'c'}
# False
(1, 2) in {('a', 'c'), (1, 2)}
# True
Si tiene la mala suerte de que el elemento que está buscando / no está buscando está al final de su lista, python habrá escaneado la lista hasta el final. Esto es evidente por los tiempos a continuación:
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)
Como recordatorio, esta es una opción adecuada siempre y cuando los elementos que está almacenando y buscando sean intercambiables. IOW, tendrían que ser tipos inmutables u objetos que se implementen __hash__
.
3 -1 > 0 and (4-1 , 5) not in []
⤇True
por lo tanto, el error no es uno de precedencia de los operadores.