Operatori Python: presentazione e spiegazione
Gli operatori Python vi aiutano a lavorare con i valori (operandi), a modificarli o a collegarli tra loro. Possono essere logici o aritmetici.
Cosa sono gli operatori Python e come funzionano?
Un operatore è un carattere per un’operazione, solitamente utilizzato per collegare diversi operandi. Di solito, viene creato un nuovo valore. L’applicazione di un operatore a un singolo operando lo modifica.
Probabilmente l’esempio più semplice di operatori Python è il collegamento di due numeri mediante l’operatore di addizione, cioè un segno più tra i numeri. Python valuta l’espressione e restituisce il valore corrispondente:
1 + 1
Una peculiarità di Python è che parole brevi come “and”, “or”, “is”, “not” o “in” vengono utilizzate come operatori in aggiunta ai simboli. La combinazione di operatori e operandi dà luogo a un’espressione:
1 + 1 == 2
Quali tipi di operatori Python esistono?
Python conosce diverse classi di operatori. Agiscono su diversi tipi di operandi e restituiscono risultati di un certo tipo. Di seguito vi riportiamo i diversi tipi di operatori Python in sintesi:
Classi di operatori Python | Spiegazione | Operandi | Risultato | Operatori in sintesi | |
---|---|---|---|---|---|
Operatori aritmetici | Combinazione di due numeri per formarne uno nuovo | Numeri | Numero | +, -, *, /, //, %, **, @ | |
Operatori di confronto | Confronto tra due espressioni | Espressioni | Booleano | <, >, ==, !=, <=, >= | |
Operatori logici | Combinazione di espressioni in un contesto booleano | Espressioni | Ultima espressione valutata / Booleano | and, or, not | |
Operatori binari | Manipolazione di interi come sequenze binarie | Numeri | Numero | <<, >>, &, | , ^, ~ |
Operatori di assegnazione | Assegnazione di un valore a un nome | Valore L, valore R | - / Espressione valutata | =, :=, +=, -=, *=, ecc. | |
Operatori di identità | Determinazione di due nomi se si riferiscono allo stesso oggetto | Oggetti | Booleano | is, is not | |
Operatori condizionali | Restituzione di uno dei due valori a seconda di una condizione | Espressione, condizione, alternativa | Espressione / Alternativa | ... if ... else ... | |
Operatori di set | Collegamento di due set / Confronto tra set | Set | Set / Booleano | &, | , ^, -, <, >, <=, >= |
Operatori di appartenenza | Verifica di un’iterabile se contiene un particolare oggetto | Oggetto, Iterabile | Booleano | in, not in | |
Operatore di concatenazione | Concatenazione di sequenze | Stringhe / Liste / Tuple | Stringa / Lista / Tupla | + | |
Operatori di indice e di fetta | Restituzione di uno o più elementi di un iterabile | Iterabile, indice / Fetta | Stringa / Lista / Tupla | [], [::] |
Oltre al tipo di operandi e al valore di ritorno, gli operatori sono classificati in base alla loro “arietà”. Il termine esprime il numero di operandi che un operatore collega. Nella maggior parte dei casi si utilizzano operatori “binari” con due operandi. Inoltre, esistono alcuni operatori “unari” con un solo operando e un operatore “ternario” che collega tre operandi:
Arietà degli operatori | Numero di operandi | Esempio |
---|---|---|
Unario | Un operando | not single_value |
Binario | Due operandi | left_operand + right_operand |
Ternario | Tre operandi | some_value if condition else other_value |
Osservare la precedenza degli operatori
Fondamentale per l’uso degli operatori Python è anche la comprensione della precedenza degli operatori. Come promemoria, l’espressione 3 * 8 + 2 viene interpretata come (3 * 8) + 2 e non come 3 * (8 + 2). Come per il più e il segno per, esistono regole di precedenza per tutti gli operatori Python. Di seguito un esempio di espressione con gli operatori logici “and”, “or” e “not”:
if is_user and is_user_logged_in or is_admin and not login_blocked:
...
Senza conoscere le regole di precedenza degli operatori Python coinvolti, è impossibile decidere come i singoli termini debbano stare insieme. Se in un’espressione vengono utilizzati più operatori, la situazione si complica rapidamente. In generale, è meglio non fare affidamento su una perfetta comprensione delle regole implicite. Si utilizzano, invece, parentesi esplicite per chiarire l’appartenenza dei termini di un’espressione:
if (is_user and is_user_logged_in) or (is_admin and not login_blocked):
...
Per un confronto, di seguito gli stessi termini raggruppati in modo diverso, in cui l’enunciato delle due espressioni è diverso:
if (is_user and is_user_logged_in or is_admin) and not login_blocked:
...
Operatori sovraccaricati, metodi Dunder e funzioni dell’operatore in Python
Alcuni operatori Python sono utilizzati per più di un’operazione. Un esempio importante è il segno più, che agisce come operatore di addizione per i numeri e allo stesso tempo come operatore di concatenazione per concatenare sequenze come stringhe e liste. Sommiamo due numeri con l’operatore di addizione:
8 + 3 == 11
Con lo stesso operatore concateniamo due stringhe:
"Walter" + "White" == "WalterWhite"
Con l’operatore più concateniamo anche delle liste:
['Jack', 'Jim'] + ['John'] == ['Jack', 'Jim', 'John']
Il molteplice uso del segno più come operatore riflette un concetto comune in informatica. Si parla di “operatori sovraccaricati” quando uno stesso operatore esegue operazioni diverse a seconda del tipo di dati degli operandi.
Come funzionano gli operatori sovraccaricati in Python? Dietro le quinte, un operatore e i suoi operandi vengono interpretati come una chiamata a una funzione corrispondente. In particolare, viene richiamato il cosiddetto metodo Dunder del primo operando, che riceve gli altri operandi come argomenti. “Dunder” sta per “double underscore”, quindi “doppio trattino basso”. Pertanto, l’operatore più corrisponde al metodo Dunder __add__(). Gli oggetti che implementano un metodo __add__() possono essere collegati con l’operatore più. Spetta all’oggetto stesso stabilire cosa costituisce esattamente il collegamento.
Oltre ai metodi Dunder, il modulo operator contiene funzioni che incapsulano le funzionalità degli operatori Python. Per esempio, “operator.add(a, b)” richiama il metodo Dunder a.__add__(b), che è equivalente all’espressione a + b. Nel resto dell’articolo elenchiamo la funzione dell’operatore per ogni operatore, se prevista. Il nome della funzione dell’operatore equivale al nome del metodo Dunder corrispondente. Utilizzatelo come riferimento per implementare la funzionalità dell’operatore:
Operatore Python | Funzione dell’operatore | Metodo Dunder |
---|---|---|
a + b | operator.add(a, b) | a.__add__(b) |
Gli operatori utilizzano la cosiddetta notazione infissa, che usa l’operatore tra gli operandi. Al contrario, lo stile funzionale utilizza la notazione prefissa. Entrambe le notazioni sono equivalenti:
Notazione | Uso | Esempio |
---|---|---|
Infissa | Operatori | a + b |
Prefissa | Funzioni | + a b / add(a, b) |
Prendiamo in considerazione un esempio. Definiamo due numeri e li sommiamo con l’operatore, la sua funzione e il metodo Dunder corrispondente:
import operator
a = 42
b = 69
assert a + b == operator.add(a, b) == a.__add__(b)
Anche espressioni più complesse possono essere scritte con le funzioni dell’operatore. Di seguito la combinazione degli operatori di addizione e uguaglianza di Python nella notazione prefissa:
import operator
assert 'Py' + 'thon' == 'Python'
assert operator.eq(operator.add('Py', 'thon'), 'Python')
Gli operatori Python in sintesi
Ora esamineremo undici diverse classi di operatori Python.
Operatori aritmetici
Gli operatori aritmetici in Python operano sui numeri, creando un nuovo numero. A eccezione degli operatori unari più e meno, sono tutti operatori binari. Qui un riepilogo:
Operatore Python | Significato | Funzione dell’operatore | Esempio |
---|---|---|---|
+ | Addizione / Più unario | add(a, b) / pos(a) | 5 + 3 == 8 / +8 == 4 + 4 |
- | Sottrazione / Meno unario | sub(a, b) / neg(a) | 7 - 2 == 5 / -4 == 2 - 6 |
* | Moltiplicazione | mul(a, b) | 2 * 3 == 6 |
/ | Divisione “pura” | truediv(a, b) | 8 / 2 == 4.0, 7 / 2 == 3.5 |
// | Divisione di un intero del numero intero immediatamente inferiore | floordiv(a, b) | 8 // 2 == 4, 7 // 2 == 3 |
% | Modulo: quantità rimanente della divisione intera | mod(a, b) | 8 % 2 == 0, 7 % 2 == 1 |
** | Esponenziazione | pow(a, b) | 2 ** 3 == 8, 10 ** -1 == 0.1 |
@ | Moltiplicazione di matrici | matmul(a, b) | – |
L’operazione modulo viene utilizzata per impostazione predefinita per determinare se un numero è pari. Questo perché un numero pari diviso per due dà resto zero. Definiamo una funzione Python corrispondente con l’operatore modulo:
def is_even(number):
return number % 2 == 0
# test
assert is_even(8) and not is_even(7)
La moltiplicazione delle matrici richiede l’uso di un pacchetto come NumPy.
Operatori di confronto Python
Gli operatori di confronto in Python forniscono una dichiarazione su come due elementi possono essere ordinati tra loro. Forniscono un risultato booleano e sono utilizzati in particolare per gli algoritmi di ordinamento:
Operatore Python | Significato | Funzione dell’operatore | Esempio |
---|---|---|---|
< | Minore di | lt(a, b) | 3 < 1, 'a' < 'z' |
> | Maggiore di | gt(a, b) | 4 > 2, 'z' > 'a' |
== | Uguale | eq(a, b) | 'a' == 'a' |
!= | Disuguale | ne(a, b) | 1 != 2, 'Jim' != 'Jack' |
<= | Minore o uguale | le(a, b) | 9 <= 10, 10 <= 10 |
>= | Maggiore o uguale | ge(a, b) | 11 >= 10, 10 >= 10 |
Operatori logici
Gli operatori logici and e or in Python collegano diversi operandi secondo la logica booleana. Di conseguenza, entrambi gli operatori restituiscono l’ultimo oggetto valutato. L’operatore logico not in Python interpreta un oggetto nel contesto booleano e nega il suo valore di verità:
Operatore Python | Significato | Funzione dell’operatore | Esempio |
---|---|---|---|
and | E logica | Nessun equivalente diretto | True and False == False, 'name' and ... == ... |
or | O logico | Nessun equivalente diretto | False or True == True, a = '' or 'Default'; assert a == 'Default' |
not | Negazione | not_(a) | not True == False |
È utile illustrare l’effetto delle operazioni logiche con le tabelle di verità. Qui viene mostrato il metodo logico AND:
and | True | False |
True | True | False |
False | False | False |
Così come l’OR logico:
or | True | False |
True | True | True |
False | True | False |
Gli operandi degli operatori booleani in Python non sono limitati alle variabili booleane. Piuttosto, qualsiasi oggetto Python può essere interpretato in un contesto booleano. I seguenti oggetti hanno una valutazione falsa nel contesto booleano e sono quindi chiamati “falsy”:
Oggetto | Spiegazione |
---|---|
False, None | Costanti che sono false per definizione |
0, 0.0, Decimal(0), Fraction(0, 1), etc. | Numero che rappresenta lo zero |
‘‘, (), [], {}, set(), range(0), etc. | Sequenza o insieme vuoti |
Operatori binari
Gli operatori binari in Python operano sui numeri interi, che vengono interpretati come sequenze di bit. A eccezione dell’operatore NOT, sono tutti operatori binari:
Operatore Python | Significato | Funzione dell’operatore | Esempio |
<< | Spostamento a sinistra della sequenza di bit | lshift(a, b) | 5 << 3 == 5 * 2 ** 3 |
>> | Spostamento a destra della sequenza di bit | rshift(a, b) | 1 >> 1 == 0, 8 >> 1 == 4 |
& | Collegamento di due sequenze di bit tramite AND | and_(a, b) | `` |
| | Collegamento di due sequenze di bit tramite OR | or_(a, b) | `` |
^ | Collegamento di due sequenze di bit tramite XOR | xor(a, b) | `` |
~ | Inversione della sequenza di bit con NOT | invert(a) | `` |
Gli operatori binari sono adatti a operazioni matematiche ottimizzate. Ad esempio, lo spostamento a sinistra corrisponde a una moltiplicazione per una potenza di due:
Espressione | 23 = 8 | 22 = 4 | 21 = 2 | 20 = 1 | Decimale |
b = 6 | 0 | 1 | 1 | 0 | 6 |
b << 1 | 1 | 1 | 0 | 0 | 12 |
b >> 1 | 0 | 0 | 1 | 1 | 3 |
Per illustrare le operazioni binarie AND, OR e NOT, costruiamo una tabella dei singoli bit. Le operazioni vengono applicate a un numero in rappresentazione binaria grazie a una maschera di bit:
Espressione | 23 = 8 | 22 = 4 | 21 = 2 | 20 = 1 | Decimale |
bits = 6 | 0 | 1 | 1 | 0 | 6 |
mask = 5 | 0 | 1 | 0 | 1 | 5 |
bits & mask | 0 | 1 | 0 | 0 | 4 |
bits | mask | 0 | 1 | 1 | 1 | 7 |
bits ^ mask | 0 | 0 | 1 | 1 | 3 |
L’operatore binario NOT in Python inverte una sequenza di bit. Ogni 1 diventa uno 0 e viceversa. Inoltre, il segno del numero è invertito:
Espressione | 23 = 8 | 22 = 4 | 21 = 2 | 20 = 1 | Decimale |
b = 6 | 0 | 1 | 1 | 0 | 6 |
~ b | 1 | 0 | 0 | 1 | -7 |
Operatori di assegnazione
Le assegnazioni sono tra le istruzioni di base della maggior parte dei linguaggi di programmazione. Gli operatori di assegnazione in Python legano un valore a un nome di variabile. Oltre all’istruzione di assegnazione, esiste il più recente operatore “tricheco”, che consente l’assegnazione all’interno di un’espressione. Esiste anche una serie di istruzioni di assegnazione estese che combinano un’assegnazione con un’altra operazione:
Operatore Python | Significato | Funzione dell’operatore | Esempio |
---|---|---|---|
= | Istruzione di assegnazione | Nessun equivalente diretto | name = 'Walther' |
:= | Espressione di assegnazione (operatore “tricheco”) | Nessun equivalente diretto | [ half for x in range(10) if (half := x / 2) < 5 ] |
+= | Assegnazione di addizione avanzata | iadd(a, b) | x = 1; x += 4; assert x == 5 |
Python conosce operatori di assegnazione avanzati per le operazioni aritmetiche e binarie. Non li elenchiamo singolarmente, ma mostriamo solo lo schema generale utilizzando l’esempio dell’assegnazione di concatenazione avanzata. Innanzitutto, viene mostrato un codice che aggiunge un’altra parte a una stringa esistente:
name = 'Walther'
name = name + 'White'
assert name == 'WaltherWhite'
Un esempio equivalente con l’operatore di concatenazione avanzato “+=” in Python, in cui si ottiene lo stesso risultato, ma il codice è più stringato e più esplicativo:
name = 'Walther'
name += 'White'
assert name == 'WaltherWhite'
Operatori di identità
L’operatore is in Python verifica se due variabili si riferiscono allo stesso oggetto in memoria. L’identità dell’oggetto è in contrasto con la sua uguaglianza, che viene verificata dall’operatore di confronto Python “==”. L’operatore “is” in Python corrisponde all’incirca all’operatore di uguaglianza rigorosa “===” di JavaScript. Python conosce anche un test d’identità negata con l’operatore “is not”:
Operatore Python | Significato | Funzione dell’operatore | Esempio |
---|---|---|---|
is | Test d’identità | is_(a, b) | a = 42; b = a; assert a is b |
is not | Test d’identità negata | is_not(a, b) | assert [42] is not [42] |
Vediamo alcuni esempi. Creiamo un riferimento a un oggetto in memoria. In seguito, creeremo un altro riferimento come alias. Se entrambe le variabili puntano allo stesso oggetto in memoria, l’operatore is restituisce “True”:
# assign value to name
a = [42]
# reference existing object
b = a
# if this holds
assert a is b
# so will this
assert a == b
Qui creiamo due riferimenti a oggetti indipendenti in memoria. Malgrado siano gli stessi, gli oggetti rimangono comunque distinti. Di conseguenza, l’operatore is restituisce “False”:
# assign the same value to different names
a = [42]
b = [42]
# `a`, `b` are two different objects
assert a is not b
# that contain the same value
assert a == b
Operatore condizionale
L’operatore condizionale in Python è un altro uso delle parole chiave if-else. Viene spesso utilizzato per distinguere tra due possibili valori nelle assegnazioni. Poiché questo operatore combina una condizione e due espressioni, è noto anche come operatore ternario.
Operatore Python | Significato | Funzione dell’operatore | Esempio |
---|---|---|---|
... if ... else ... | Espressione condizionale | Nessun equivalente diretto | name = 'Jim' if age == 42 else 'Jack' |
Vediamo prima un esempio utilizzando l’istruzione if-else in Python. Il codice seguente imposta Celsius o Fahrenheit come unità di misura della temperatura, a seconda del sistema di misura selezionato:
if system == 'metric':
unit = 'C'
else:
unit = 'F'
Utilizzando l’operatore condizionale, il codice può essere semplificato in un singolo assegnamento:
unit = 'C' if system == 'metric' else 'F'
Operatori di set in Python
Oltre a stringhe, tuple, liste e dizionari, Python supporta per impostazione predefinita i set come tipo di dati composito. Gli operatori sovraccaricati sono definiti per le consuete operazioni sui set:
Operatore Python | Significato | Funzione dell’operatore | Esempio | ||
---|---|---|---|---|---|
& | Creazione dell’unione di due set | and_(a, b) | {'a', 'b'} & {'a', 'c'} == {'a'} | ||
Creazione dell’intersezione di due set | or_(a, b) | {'a', 'b'} | {'a', 'c'} == {'a', 'c', 'b'} | ||
^ | Creazione della differenza simmetrica di due set | xor(a, b) | {'a', 'b'} ^ {'a', 'c'} == {'c', 'b'} | ||
- | Creazione della differenza di due set | sub(a, b) | {'a', 'b'} - {'a'} == {'b'} | ||
> | Verifica se un insieme è un vero superset | gt(a, b) | assert {'a', 'b'} > {'a'} | ||
>= | Verifica se un insieme è un superset | ge(a, b) | assert {'a'} >= {'a'} | ||
< | Verifica se un insieme è un vero subset | lt(a, b) | assert {'a'} < {'a', 'b'} | ||
<= | Verifica se un insieme è un subset | le(a, b) | assert {'a'} <= {'a'} |
Operatori di appartenenza in Python
Gli operatori di appartenenza “in” e “not in” in Python forniscono una dichiarazione sull’inclusione di un oggetto in un insieme.
Operatore Python | Significato | Funzione dell’operatore | Esempio |
---|---|---|---|
in | Verifica se un oggetto è contenuto in un’iterabile | contains(a, b) | 'y' in 'Python' |
not in | Negazione dell’operatore in | not contains(a, b) | 'x' not in 'Python' |
Gli operatori di appartenenza funzionano con iterabili e utilizzano un controllo di uguaglianza per determinare se l’oggetto di destinazione è incluso nell’insieme:
'Py' in 'Python'
'Px' not in 'Python'
'Jack' in ['Jim', 'Jack']
L’uso dell’operatore in consente di evitare di scrivere il codice nella forma seguente:
def my_in(target, collection):
for element in collection:
if element == target:
return True
return False
# test
word = 'Python'
letter = 'y'
assert (my_in(letter, word)) == (letter in word)
Operatore di concatenazione
In Python, l’operatore di concatenazione viene utilizzato per concatenare sequenze dello stesso tipo. Il segno più viene utilizzato come simbolo dell’operatore.
Operatore Python | Significato | Funzione dell’operatore | Esempio |
---|---|---|---|
+ | Concatena due sequenze | add(a, b) | ['Jim'] + ['Jack', 'John'] |
Vediamo alcuni esempi. Concateniamo due stringhe, due liste e due tuple:
assert "Walter" + "White" == 'WalterWhite'
assert ['a', 'b'] + ['c'] == ['a', 'b', 'c']
assert ('q', 'r') + ('s', 't') == ('q', 'r', 's', 't')
Python è utilizzato come linguaggio di programmazione web. In questo contesto, l’operatore di concatenazione viene utilizzato per assemblare tag HTML:
site_title = 'Welcome'
print('<h1>' + site_title + '</h1>')
Nel confronto tra Python e PHP viene fatta una distinzione tra gli operatori di concatenazione dei due linguaggi. Questo perché PHP utilizza il punto “.” come simbolo. Lo stesso esempio mostrato in PHP:
$siteTitle = 'Welcome';
echo '<h1>' . $siteTitle . '</h1>';
Operatori di indice e di fetta
L’operatore indice in Python viene utilizzato per estrarre un elemento specifico di un insieme. L’operatore fetta (“slice” in inglese) viene utilizzato per estrarre una sottosequenza.
Operatore Python | Significato | Funzione dell’operatore | Esempio |
---|---|---|---|
iterable[index] | Restituisce l’elemento di un iterabile situato sotto l’indice | getitem(iterable, index) | 'Python'[1] == 'y' |
sequence[start:stop:step] | Restituisce una fetta di una sequenza | getitem(iterable, slice(start, stop, step)) | 'Python'[0:1] == 'Py', 'Python'[0:-1:2] == 'Pto' |
Gli operatori indice e fetta di Python fanno uso interno del metodo Dunder __getitem__(), che viene richiamato con un indice numerico o con un oggetto fetta:
names = ['Jim', 'Jack', 'John']
names[0] == names.__getitem__(0)
names[0:2] == names.__getitem__(slice(0, 2))
L’operatore fetta è utile perché consente di estrarre una sottosequenza senza usare un ciclo for in Python o un ciclo while in Python. Questo evita ai programmatori di scrivere un codice nella forma seguente:
word = 'Python'
start, stop, step = 0, 5, 2
index, substring = start, ''
while index in range(start, stop, step):
substring += word[index]
index += step
# test
assert substring == word[start:stop:step]