Come posso verificare se qualcosa è (non) in un elenco in Python?
La soluzione più economica e più leggibile sta utilizzando l' in
operatore (o nel tuo caso specifico not in
). Come menzionato nella documentazione,
Gli operatori in
e not in
test per l'adesione. x in s
valuta
True
se x
è membro di s
, e False
altrimenti. x not in s
restituisce la negazione di x in s
.
Inoltre,
L'operatore not in
è definito per avere il valore reale inverso di in
.
y not in x
è logicamente uguale a not y in x
.
Ecco alcuni esempi:
'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
Questo funziona anche con le tuple, poiché le tuple sono irritabili (come conseguenza del fatto che sono anche immutabili):
(1, 2) in [(3, 4), (1, 2)]
# True
Se l'oggetto su RHS definisce un __contains__()
metodo, in
lo chiamerà internamente, come indicato nell'ultimo paragrafo della sezione Confronti dei documenti.
... in
e not in
sono supportati da tipi iterabili o implementano il
__contains__()
metodo. Ad esempio, potresti (ma non dovresti) fare questo:
[3, 2, 1].__contains__(1)
# True
in
cortocircuiti, quindi se il tuo elemento è all'inizio dell'elenco, in
valuta più velocemente:
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 vuoi fare di più che controllare se un elemento è in un elenco, ci sono opzioni:
list.index
può essere utilizzato per recuperare l'indice di un elemento. Se quell'elemento non esiste, ValueError
viene sollevato a.
list.count
può essere utilizzato se si desidera contare le occorrenze.
Il problema XY: hai considerato set
s?
Ponetevi queste domande:
- devi verificare se un elemento è in un elenco più di una volta?
- Questo controllo viene eseguito all'interno di un ciclo o una funzione chiamata ripetutamente?
- Gli elementi che stai memorizzando nel tuo elenco sono cancellabili? IOW, puoi chiamarli
hash
?
Se hai risposto "sì" a queste domande, dovresti usare set
invece un . Un in
test di appartenenza su list
s è O (n) complessità temporale. Ciò significa che python deve eseguire una scansione lineare dell'elenco, visitando ogni elemento e confrontandolo con l'elemento di ricerca. Se lo fai ripetutamente o se gli elenchi sono grandi, questa operazione comporterà un sovraccarico.
set
gli oggetti, d'altra parte, eseguono l'hashing dei loro valori per un controllo costante dell'appartenenza a tempo. Il controllo viene inoltre eseguito utilizzando in
:
1 in {1, 2, 3}
# True
'a' not in {'a', 'b', 'c'}
# False
(1, 2) in {('a', 'c'), (1, 2)}
# True
Se sei abbastanza sfortunato che l'elemento che stai cercando / non stai cercando sia alla fine della tua lista, Python avrà scannerizzato la lista fino alla fine. Ciò è evidente dai tempi seguenti:
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)
Come promemoria, questa è un'opzione adatta a condizione che gli elementi che stai memorizzando e guardando siano hash. IOW, dovrebbero essere tipi immutabili o oggetti che implementano __hash__
.
3 -1 > 0 and (4-1 , 5) not in []
⤇True
pertanto l'errore non è una priorità dell'operatore.