
In Python, gli operatori in e non nell’appartenenza al test in elenchi, tuple, dizionari e così via.
In questo articolo vengono descritti i seguenti contenuti.
- Vieni a utilizzare l’operatore in
- Utilizzo di base
- Testato se hanno lo stesso valore
- Con l’istruzione se
- nel dizionario (dict)
- dentro per la stringa (str)
- non in (negazione di in)
- per più elementi
- Complessità temporale di in
- Lento per la lista:
O(n)
- Veloce per il set:
O(1)
- Per il dizionario
- Lento per la lista:
- in per dichiarazioni e comprensioni di elenchi
La parola in è usata anche per affermazioni e comprensioni di elenchi. Vedere i seguenti articoli per i dettagli.
Vieni a utilizzare l’operatore in
Utilizzo di base
x in y restituisce True se x è incluso in ye False se non lo è.
print(1 in [0, 1, 2])
# True
print(100 in [0, 1, 2])
# False
Non solo elenco, ma anche tupla, set, intervallo e altri oggetti iterabili possono essere utilizzati.
print(1 in (0, 1, 2))
# True
print(1 in {0, 1, 2})
# True
print(1 in range(3))
# True
Il dizionario (dict) e la stringa (str) sono più descritti avanti.
Testato se hanno lo stesso valore
Il test di in si basa sul fatto che i valori sono uguali o meno e su ==. È True se il valore è uguale anche se il tipo è diverso.
print(1.0 == 1)
# True
print(1.0 in [0, 1, 2])
# True
print(True == 1)
# True
print(True in [0, 1, 2])
# True
Nota che bool è una sottoclasse di int intero, quindi True e False equivalgono rispettivamente a 1 e 0.
Con l’istruzione se
in restituisce un valore bool (True, False) e può essere utilizzato direttamente nell’istruzione if.
l = [0, 1, 2]
i = 0
if i in l:
print(f'{i} is a member of {l}.')
else:
print(f'{i} is not a member of {l}.')
# 0 is a member of [0, 1, 2].
l = [0, 1, 2]
i = 100
if i in l:
print(f'{i} is a member of {l}.')
else:
print(f'{i} is not a member of {l}.')
# 100 is not a member of [0, 1, 2].
Si noti che elenchi, tuple, stringhe, ecc. vengono valutati come False se sono vuoti e True se non lo sono. Se vuoi controllare se un oggetto è vuoto o meno, puoi usare l’oggetto così com’è.
l = [0, 1, 2]
if l:
print(f'{l} is not empty.')
else:
print(f'{l} is empty.')
# [0, 1, 2] is not empty.
l = []
if l:
print(f'{l} is not empty.')
else:
print(f'{l} is empty.')
# [] is empty.
Vedere anche i seguenti articoli per la verifica del valore di verità per ciascun tipo.
nel dizionario (dict)
I test in funzione per il dizionario (dict) sulla chiave.
d = {'key1': 'value1', 'key2': 'value2', 'key3': 'value3'}
print('key1' in d)
# True
print('value1' in d)
# False
Usa values(), items() se vuoi testare valori o coppie chiave-valore.
print('value1' in d.values())
# True
print(('key1', 'value1') in d.items())
# True
print(('key1', 'value2') in d.items())
# False
Vedere il seguente articolo per i dettagli.
dentro per la stringa (str)
L’operazione in corso per la stringa (str) verifica l’esistenza di una sottostringa.
print('a' in 'abc')
# True
print('x' in 'abc')
# False
print('ab' in 'abc')
# True
print('ac' in 'abc')
# False
non in (negazione di in)
x non in y riporta la negazione di x in y.
print(10 in [1, 2, 3])
# False
print(10 not in [1, 2, 3])
# True
Lo stesso risultato viene restituito aggiungendo non all’intera operazione.
print(not 10 in [1, 2, 3])
# True
Tuttavia, se si aggiunge non all’intero in operazione, verrà interpretato in due modi, come mostrato di seguito, quindi si consiglia di utilizzare il più esplicito non in.
print(not (10 in [1, 2, 3]))
# True
print((not 10) in [1, 2, 3])
# False
Poiché in ha una precedenza maggiore rispetto a non, viene trattato come il primo se non ci sono parentesi.
Quest’ultimo caso è riconosciuto come segue.
print(not 10)
# False
print(False in [1, 2, 3])
# False
per più elementi
Se si desidera verificare se sono inclusi più elementi, l’utilizzo di un elenco di tali elementi come segue non funzionerà. Verrà verificato se l’elenco stesso è incluso o meno.
print([0, 1] in [0, 1, 2])
# False
print([0, 1] in [[0, 1], [1, 0]])
# True
Usa e, oo imposta.
Usa e, o
Combina più nelle operazioni usando ee o. Verrà verificato se entrambi o entrambi sono inclusi.
l = [0, 1, 2]
v1 = 0
v2 = 100
print(v1 in l and v2 in l)
# False
print(v1 in l or v2 in l)
# True
print((v1 in l) or (v2 in l))
# True
Poiché in e non hanno una precedenza maggiore di eeo, le parentesi non sono necessarie. Naturalmente, se è di lettura difficile, lo si può racchiudere tra parentesi come nell’ultimo esempio.
Insieme degli Stati Uniti
Se hai molti elementi che vuoi controllare, è più facile usare il set di e, o.
Ad esempio, se l’elenco A contiene tutti gli elementi dell’elenco B equivale a se l’elenco B è un sottoinsieme dell’elenco A.
l1 = [0, 1, 2, 3, 4]
l2 = [0, 1, 2]
l3 = [0, 1, 5]
l4 = [5, 6, 7]
print(set(l2) <= set(l1))
# True
print(set(l3) <= set(l1))
# False
Se la lista A non contiene gli elementi della lista B equivale a se la lista A e la lista B sono relative prime.
print(set(l1).isdisjoint(set(l4)))
# True
Se la lista A e la lista B non sono relative prime, significa che la lista contiene almeno un elemento della lista B.
print(not set(l1).isdisjoint(set(l3)))
# True
Complessità temporale di in
La velocità di esecuzione dell’operatore in dipende dal tipo di oggetto target.
Di seguito sono seguiti i risultati della misurazione del tempo di esecuzione di in per elenchi, set e dizionari.
Si noti che il codice seguente utilizza il comando magico di Jupyter Notebook %%timeit e non funziona se come script Python.
Vedere il seguente articolo per la complessità del tempo.
Prendi un esempio di 10 elementi e 10000 elementi come.
n_small = 10
n_large = 10000
l_small = list(range(n_small))
l_large = list(range(n_large))
Il codice di esempio seguente viene eseguito in CPython 3.7.4 e, naturalmente, i risultati possono variare a seconda dell’ambiente.
Lento per l’elenco: O(n)
La complessità temporale media dell’operatore in per le liste è O(n). Diventa più lento quando ci sono molti elementi.
%%timeit
-1 in l_small
# 178 ns ± 4.78 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
%%timeit
-1 in l_large
# 128 µs ± 11.5 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
Il tempo di esecuzione varia notevolmente a seconda della posizione del valore da cercare. Ci vuole il tempo più lungo quando il suo valore è alla fine o non esiste.
%%timeit
0 in l_large
# 33.4 ns ± 0.397 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
%%timeit
5000 in l_large
# 66.1 µs ± 4.38 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
%%timeit
9999 in l_large
# 127 µs ± 2.17 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
Veloce per il set: O(1)
La complessità temporale media dell’operatore in per gli insiemi è O(1). Non dipende dal numero di elementi.
s_small = set(l_small)
s_large = set(l_large)
%%timeit
-1 in s_small
# 40.4 ns ± 0.572 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
%%timeit
-1 in s_large
# 39.4 ns ± 1.1 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
Il tempo di esecuzione non cambia a seconda del valore da cercare.
%%timeit
0 in s_large
# 39.7 ns ± 1.27 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
%%timeit
5000 in s_large
# 53.1 ns ± 0.974 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
%%timeit
9999 in s_large
# 52.4 ns ± 0.403 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
Se si desidera ripetere l’operazione per un elenco con molti elementi, è più rapido convertirlo in un insieme in anticipo.
%%timeit
for i in range(n_large):
i in l_large
# 643 ms ± 29.8 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%%timeit
s_large_ = set(l_large)
for i in range(n_large):
i in s_large_
# 746 µs ± 6.7 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
Si noti che la conversione di un elenco in un set richiede tempo, quindi potrebbe essere più veloce mantenerlo come elenco se il numero di operazioni in è piccolo.
Per il dizionario
Prendi il seguente dizionario come esempio.
d = dict(zip(l_large, l_large))
print(len(d))
# 10000
print(d[0])
# 0
print(d[9999])
# 9999
Come accennato in precedenza, è in funzione per i test del dizionario sui tasti.
La chiave del dizionario è un valore univoco così come l’insieme e il tempo di esecuzione è più o meno lo stesso degli insiemi.
%%timeit
for i in range(n_large):
i in d
# 756 µs ± 24.9 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
D’altra parte, i valori del dizionario possono essere duplicati come un elenco. Il tempo di esecuzione di in for values() è più o meno lo stesso delle liste.
dv = d.values()
%%timeit
for i in range(n_large):
i in dv
# 990 ms ± 28.8 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
Le coppie chiave-valore sono uniche. Il tempo di esecuzione di in for items() è di circa set + α.
di = d.items()
%%timeit
for i in range(n_large):
(i, i) in di
# 1.18 ms ± 26.2 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
in per dichiarazioni e comprensioni di elenchi
La parola in è usata anche per affermazioni e comprensioni di elenchi.
l = [0, 1, 2]
for i in l:
print(i)
# 0
# 1
# 2
print([i * 10 for i in l])
# [0, 10, 20]
Vedere i seguenti articoli per i dettagli sulle dichiarazioni e la comprensione degli elenchi.
Si noti che l’operatore in può essere utilizzato come condizione nelle comprensioni degli elenchi, il che crea confusione.
l = ['oneXXXaaa', 'twoXXXbbb', 'three999aaa', '000111222']
l_in = [s for s in l if 'XXX' in s]
print(l_in)
# ['oneXXXaaa', 'twoXXXbbb']
Il primo in è per la comprensione dell’elenco e il secondo in è l’operatore in.