Esta es la solución más exacta que encomtrarás compartir, pero primero mírala pausadamente y valora si se adapta a tu proyecto.
Solución:
El error probablemente esté en otro lugar de su código, porque debería funcionar bien:
>>> 3 not in [2, 3, 4]
False
>>> 3 not in [4, 5, 6]
True
O con tuplas:
>>> (2, 3) not in [(2, 3), (5, 6), (9, 1)]
False
>>> (2, 3) not in [(2, 7), (7, 3), "hi"]
True
¿Cómo verifico si algo está (no) en una lista en Python?
La solución más barata y legible es usar el in
operador (o en su caso específico, not in
). Como se menciona en la documentación,
los operadores
in
ynot in
prueba de membresía.x in s
evalúa a
True
six
es miembro des
yFalse
de lo contrario.x not in s
devuelve la negación dex in s
.
Además,
El operador
not in
se define para tener el inverso true valor dein
.
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 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 indica en el último párrafo de la sección Comparaciones de los docs.
…
in
ynot 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 algo más que simplemente verificar si un elemento está en una lista, hay opciones:
list.index
se puede utilizar para recuperar el índice de un elemento. Si ese elemento no existe, unValueError
es elevado.list.count
se puede utilizar si desea contar las ocurrencias.
El problema XY: ¿Has considerado set
¿s?
Hazte estas preguntas:
- ¿Necesita verificar si un elemento está en una lista más de una vez?
- ¿Esta verificación se realiza dentro de un bucle o es una función llamada repetidamente?
- ¿Los elementos que está almacenando en su lista son hashable? IOW, ¿puedes llamar?
hash
¿en ellos?
Si respondió “sí” a estas preguntas, debería estar usando un set
en cambio. Un in
prueba de membresía en list
s es O(n) complejidad temporal. 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 hace esto repetidamente, o si las listas son grandes, esta operación generará una sobrecarga.
set
los objetos, por otro lado, codifican sus valores para la verificación de membresía de tiempo constante. La comprobación también se realiza mediante 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 o no está al final de su lista, Python habrá escaneado la lista hasta el final. Esto es evidente a partir de 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 que los elementos que esté almacenando y buscando sean hashable. IOW, tendrían que ser tipos inmutables u objetos que implementen __hash__
.
Acuérdate de que te brindamos la opción de añadir una evaluación correcta si descubriste tu problema en el momento justo.