Un operatore di confronto in Python (detto anche operatore relazionale di Python) esamina i valori di due operandi e restituisce un booleano True o False a seconda che la condizione comparison sia soddisfatta o meno.
La tabella seguente mostra gli operatori di confronto più comuni di Python:
| Operatore | Operazione | Descrizione |
|---|---|---|
> |
«maggiore di» |
a > b è True se a è strettamente maggiore di b in valore |
< |
«minore di» |
a < b è True se a è strettamente minore di b in valore |
== |
«uguale a» |
a == b è True se a è strettamente uguale a b in valore |
>= |
«maggiore o uguale a» |
a >= b è True se a > b oppure a == b in valore |
<= |
«minore o uguale a» |
a <= b è True se a < b o a == b in valore |
!= |
«diverso da» |
a != b è True se a == b è False
|
is |
«identità» |
a is b è True se e solo se a e b sono lo stesso oggetto
|
is not |
«identità negata» |
a is not b è True se e solo se a e b non sono lo stesso oggetto
|
in |
«test di appartenenza» |
a in b è True se a è membro, sottoinsieme o elemento di b
|
not in |
«test di appartenenza negato» |
a not in b è True se a non è un membro, un sottoinsieme o un elemento di b
|
Hanno tutti la stessa priorità (maggiore di quella delle operazioni booleane, ma minore di quella delle operazioni aritmetiche o bit a bit).
Gli oggetti di tipo diverso (tranne i tipi numerici) non risultano mai uguali per impostazione predefinita.
Anche le istanze non identiche di una class non risultano uguali, a meno che la class non definisca speciali metodi di confronto avanzato che personalizzano il comportamento di confronto predefinito di object.
Per (molti) più dettagli, vedi Confronti tra valori nella documentazione di Python.
I tipi numerici sono (in gran parte) un'eccezione a questa regola di corrispondenza tra tipi.
Un integer può essere considerato uguale a un float (o un octal uguale a un hexadecimal), purché i tipi possano essere convertiti implicitamente per il confronto.
Per gli altri tipi numerici (complessi, decimali, frazioni), gli operatori di confronto sono definiti dove «ha senso» (dove la conversione implicita non cambia il risultato), ma sollevano un TypeError se gli oggetti sottostanti non possono essere convertiti accuratamente per il confronto.
Per maggiori informazioni sulle regole che Python usa per la conversione numerica, vedi conversioni aritmetiche nella documentazione di Python.
>>> import fractions
# A string cannot be converted to an int.
>>> 17 == '17'
False
# An int can be converted to float for comparison.
>>> 17 == 17.0
True
# The fraction 6/3 can be converted to the int 2
# The int 2 can be converted to 0b10 in binary.
>>> 6/3 == 0b10
True
# An int can be converted to a complex
# number with a 0 imaginary part.
>>> 17 == complex(17)
True
# The fraction 2/5 can be converted to the float 0.4
>>> 0.4 == 2/5
True
>>> complex(2/5, 1/2) == complex(0.4, 0.5)
True
Qualsiasi confronto ordinato tra un numero e un tipo NaN (not a number) è False.
Un effetto collaterale confuso della definizione di NaN in Python è che NaN non risulta mai uguale a NaN.
Se sei curioso di sapere perché NaN è stato definito così in Python, questo post su Stack Overflow riguardo a NaN, sulla definizione dello standard internazionale, è una lettura interessante.
>>> x = float('NaN')
>>> 3 < x
False
>>> x < 3
False
# NaN never compares equal to NaN
>>> x == x
False
Le stringhe (str) vengono confrontate in ordine lessicografico, usando i singoli punti di codice Unicode (il risultato del passaggio di ogni punto di codice nella str alla funzione incorporata ord(), che restituisce un int).
Se tutti i punti di codice di entrambe le stringhe coincidono e sono nello stesso ordine, le due stringhe sono considerate uguali.
Questo confronto avviene in modo «a coppie»: primo con primo, secondo con secondo, e così via.
In Python 3.x, str e bytes non possono essere convertiti/confrontati direttamente.
>>> 'Python' > 'Rust'
False
>>> 'Python' > 'JavaScript'
True
# Examples with Mandarin.
# hello < goodbye
>>> '你好' < '再见'
True
# ord() of first characters
>>> ord('你'), ord('再')
(20320, 20877)
# ord() of second characters
>>> ord('好'), ord('见')
(22909, 35265)
# And with Korean words.
# Pretty < beautiful.
>>> '예쁜' < '아름다운'
False
>>> ord('예'), ord('아')
(50696, 50500)
Anche i tipi di dati contenitore (lists, tuples, sets, dicts, ecc.) si confrontano in ordine lessicografico: sono uguali se entrambi i contenitori hanno gli stessi dati e gli stessi tipi di dati (nel caso di lists e tuples, devono avere anche lo stesso ordinamento), in caso contrario sono diversi.
>>> [1, 2] == [1, 2]
True
# But if the data is not in the same order, they are not equal.
>>> [2, 1] == [1, 2]
False
# The same holds true for tuples
>>> (3,4,5) == (5,4,3)
False
# Length is also compared
>>> [1, 2] < [1, 2, 3]
True
# Comparing dicts
>>> {'name': 'John', 'age': 19} == {'name': 'John', 'age': 18}
False
>>> {'name': 'John', 'age': 19} == {'name': 'John', 'age': 19}
True
Gli operatori di confronto possono essere concatenati arbitrariamente.
Nota che la valutazione di un'espressione avviene da left a right.
Per esempio, x < y <= z è equivalente a x < y and y <= z, tranne per il fatto che y viene valutato una sola volta.
In entrambi i casi, z non viene valutato affatto quando si scopre che x < y è False.
Questo è spesso chiamato short-circuit evaluation: la valutazione si interrompe se il valore di verità dell'espressione è già stato determinato.
Lo Short circuiting è supportato da vari operatori booleani, funzioni e anche dalla concatenazione di confronti in Python.
A differenza di molti altri linguaggi di programmazione, tra cui C, C++, C# e Java, le espressioni concatenate come a < b < c in Python hanno una interpretazione matematica e una precedenza convenzionali.
>>> x = 2
>>> y = 5
>>> z = 10
>>> x < y < z
True
>>> x < y > z
False
>>> x > y < z
False
Gli operatori is e is not verificano l'identità di un oggetto, al contrario del valore dell'oggetto.
L'identità di un oggetto non cambia mai dopo la sua creazione e può essere trovata usando la funzione id().
<apple> is <orange> restituisce True se e solo se id(<apple>) == id(<orange>).
<apple> is not <orange> restituisce l'inverso.
A causa del loro stato di singleton, None e NotImplemented dovrebbero sempre essere confrontati con gli elementi usando is e is not.
Vedi la documentazione di riferimento di Python sui confronti di valori e su PEP8 per maggiori dettagli su questa convenzione.
# A list of favorite numbers.
>>> my_fav_numbers = [1, 2, 3]
>>> your_fav_numbers = my_fav_numbers
>>> my_fav_numbers is your_fav_numbers
True
# The returned id will differ by system and Python version.
>>> id(my_fav_numbers)
4517478208
# your_fav_numbers is only an alias pointing to the original my_fav_numbers object.
# Assigning a new name does not create a new object.
>>> id(your_fav_numbers)
4517478208
>>> my_fav_numbers is not your_fav_numbers
False
>>> my_fav_numbers is not None
True
>>> my_fav_numbers is NotImplemented
False
Gli operatori in e not in verificano l'appartenenza.
<fish> in <soup> restituisce True se <fish> è un membro di <soup> (se <fish> è un sottoinsieme di <soup> o è contenuto in <soup>), altrimenti restituisce False.
<fish> not in <soup> restituisce la negazione, ovvero l'opposto di <fish> in <soup>.
Per i tipi stringa e bytes, <name> in <fullname> è True se e solo se <name> è una sottostringa di <fullname>.
# A set of lucky numbers.
>>> lucky_numbers = {11, 22, 33}
>>> 22 in lucky_numbers
True
>>> 44 in lucky_numbers
False
# A dictionary of employee information.
>>> employee = {'name': 'John Doe', 'id': 67826, 'age': 33, 'title': 'ceo'}
# Checking for the membership of certain keys.
>>> 'age' in employee
True
>>> 33 in employee
False
>>> 'lastname' not in employee
True
# Checking for substring membership
>>> name = 'Super Batman'
>>> 'Bat' in name
True
>>> 'Batwoman' in name
False
Il comportamento di confronto degli oggetti può essere personalizzato tramite l'implementazione dei rich comparison methods.
Per maggiori informazioni, vedi Tutorial di Python: classi, Python Classes and Magic Methods (Dan Bader) e Nomi di metodi speciali.