Vai al contenuto principale

Operatori logici in Python: un’introduzione pratica

Python offre tre operatori logici: and, or e not. Questi operatori, noti anche come booleani, valutano più condizioni e determinano il valore di verità complessivo di un’espressione.
· 13 min leggi

Scopri con l'IA

In programmazione, capita spesso di dover prendere decisioni basate su più condizioni. Per esempio, potremmo voler eseguire una certa azione solo se più condizioni sono soddisfatte contemporaneamente. In alternativa, potremmo voler attivare un’azione diversa se almeno una di diverse condizioni è verificata.

Python mette a disposizione un insieme di operatori logici – and, or, not – per gestire questi scenari.

In questo tutorial vedremo come funzionano gli operatori logici di Python e come usarli in programmazione e data science. Nota che useremo le parole maiuscole AND, OR e NOT per rappresentare concettualmente questi operatori. E ci riferiremo alle keyword Python usando questa convenzione: and, or e not.

Se cerchi un percorso Python curato, dai un’occhiata a questo skill track in sei corsi: Python Programming.

Prima di entrare nei dettagli, iniziamo con una risposta molto breve per chi ha fretta.

Risposta breve: cosa sono gli operatori logici in Python?

Gli operatori logici di Python (and, or, not) sono keyword speciali che agiscono come congiunzioni nel codice, collegando e valutando più condizioni all’interno di un’unica espressione.

Considera questo esempio:

temperature = 25
is_sunny = True
if temperature > 20 and is_sunny:
    print("It's a perfect day for a picnic!")
It's a perfect day for a picnic!

Qui, l’operatore and fa sì che il messaggio venga stampato solo se entrambe le condizioni sono soddisfatte: la temperatura è sopra i 20 gradi e c’è il sole.

Vediamo un altro esempio con l’operatore or:

has_umbrella = False

if is_sunny or has_umbrella:
    print("Let's go for a walk!")
Let's go for a walk!

In questo caso, usciremo a fare una passeggiata se o c’è il sole o abbiamo un ombrello.

Infine, l’operatore not inverte il valore di verità di una condizione:

if not is_sunny:
    print("Maybe we should stay indoors.")

Qui, il messaggio viene stampato solo se non c’è il sole.

Gli operatori logici offrono un modo conciso e potente per esprimere condizioni complesse, consentendo ai nostri programmi di prendere decisioni basate su più fattori. Ora andiamo più a fondo e partiamo dall’operatore logico and.

Python: l’operatore and

Nella logica booleana, l’operazione AND confronta due valori o espressioni. Restituisce vero solo se entrambi i valori sono veri. Se uno dei due o entrambi i valori sono falsi, il risultato dell’operazione AND è falso. Ecco un riepilogo del comportamento di AND:

Operazione

Valore in uscita

true AND true

true

true AND false

false

false AND true

false

false AND false

false

Possiamo ricreare questa tavola di verità con l’operatore and di Python:

options = True, False
for a in options:
    for b in options:
        print(f"{a} and {b} gives {a and b}")
True and True gives True
True and False gives False
False and True gives False
False and False gives False

La variabile options contiene i due valori booleani. I cicli for annidati iterano due volte su options per creare tutte le permutazioni di True e False.

Spesso, le espressioni usate come operandi di and includono operatori di confronto o uguaglianza:

names = "James", "Bob", "David", "Jane", "Kate", "Mary"
for name in names:
   if len(name) < 5 and name[0] == "J":
      print(name)
Jane

Il nome viene stampato solo se contiene meno di cinque lettere e inizia con "J". Entrambi i requisiti devono essere soddisfatti.

Gli operatori di confronto e uguaglianza, come < e ==, restituiscono True o False.

Tuttavia, l’operatore and di Python funziona su qualsiasi tipo di dato e non solo sui booleani True e False. Anche il valore restituito può essere di qualsiasi tipo.

Esploriamo più in dettaglio l’operatore and di Python in questa sezione. Per prima cosa, parliamo di truthiness.

Python: truthy e falsy

Ogni oggetto Python può essere convertito in un tipo booleano usando la built-in bool(). Un oggetto è truthy se bool(object) restituisce True. Per un oggetto falsy, bool(object) restituisce False.

L’operatore and di Python guarda alla truthiness dei suoi operandi. Se entrambi gli operandi sono truthy, l’operatore and restituisce a sua volta un valore truthy. Se uno o entrambi gli operandi sono falsy, and restituisce un valore falsy. Vediamo alcuni esempi:

if 42 and "python":
    print("Both operands are truthy")
else:
    print("One or both operands are falsy")
Both operands are truthy

Ora, considera questo esempio:

if 42 and "":
    print("Both operands are truthy")
else:
    print("One or both operands are falsy")
One or both operands are falsy

E diamo un’occhiata a quest’ultimo esempio:

if 0 and "python":
    print("Both operands are truthy")
else:
    print("One or both operands are falsy")
One or both operands are falsy

I tipi numerici, come interi e float, sono truthy se non sono zero e falsy quando sono uguali a zero. Le sequenze, come le stringhe, sono truthy quando non sono vuote e falsy quando sono vuote.

Di conseguenza, solo il primo dei tre esempi sopra soddisfa la condizione che entrambi gli operandi siano truthy perché l’operatore and valuti a truthy.

L’operatore and non restituisce sempre un valore booleano. Un’espressione che include and può anche valutare a uno degli operandi. Approfondiamo usando gli stessi esempi di prima. Invece di usare le espressioni con and in un’istruzione if, le valuteremo direttamente:

print(42 and "python")
print(42 and "")
print(0 and "python")
python

0

Riesci a cogliere cosa succede con queste espressioni?

Partiamo dall’ultimo dei tre esempi, che ha 0 e "python" come operandi. L’operatore and cerca due operandi truthy. Poiché il primo è 0, è falsy. Non c’è bisogno che il programma controlli il secondo operando, dato che l’intera espressione sarà falsy a prescindere dal valore del secondo.

Tuttavia, l’operatore and non restituisce False. Restituisce invece direttamente il primo operando. Poiché il primo operando è falsy, l’intera espressione con and valuta a falsy. Questo non crea problemi in Python, perché quando è richiesto un valore vero o falso, può essere usata la truthiness di un oggetto.

Nel primo esempio, il primo operando è 42, che è truthy. Il programma valuta il secondo operando e lo restituisce. Poiché il secondo operando è la stringa "python", che è truthy, l’intera espressione valuta come truthy.

Nel secondo esempio, anche il primo operando è 42. Essendo truthy, il programma valuta e restituisce il secondo operando, che è la stringa vuota. La stringa vuota è falsy e, quindi, l’intera espressione and valuta a falsy.

Quando il primo operando è truthy, l’operatore and restituisce sempre il valore del secondo operando, sia che questo sia truthy o falsy.

Quando il primo operando è falsy, Python non valuta il secondo operando. Questo si chiama short-circuiting ed è una forma di valutazione pigra. Puoi verificarlo con il seguente codice:

0 and 5/0
0

Il secondo operando è 5/0, che normalmente solleverebbe un’eccezione ZeroDivisionError. Tuttavia, l’espressione 5/0 non viene valutata in questo esempio perché il primo operando è falsy. L’eccezione non viene mai sollevata.

Esempio: il negozio online per programmatori

Consideriamo un semplice esempio che rappresenta un’applicazione reale. Le transazioni in un negozio online che fornisce articoli per programmatori sono registrate e accessibili tramite un’API. I dati vengono convertiti in una lista di dizionari. Ogni elemento della lista rappresenta una transazione e ogni transazione è un dizionario che contiene le informazioni rilevanti:

data = [
{"Item": "Python Book", "Price": 50, "Quantity": 1, "Success": True},
{"Item": "Coffee Machine", "Price": 125, "Quantity": 1, "Success": False},
{"Item": "Headphones", "Price": 250, "Quantity": 1, "Success": True},
{"Item": "Cables", "Price": 15.99, "Quantity": 3, "Success": True},
]

Ogni transazione include il nome e il prezzo dell’articolo, la quantità inclusa nell’ordine e se la transazione è andata a buon fine.

Supponiamo di aver bisogno delle transazioni riuscite per articoli con prezzo pari o superiore a 100 $. Possiamo usare l’operatore and per filtrare le righe che ci servono:

for item in data:
    if item["Success"] and item["Price"] >= 100:
        print(item)
{'Item': 'Headphones', 'Price': 250, 'Quantity': 1, 'Success': True}

L’output mostra l’unica transazione che soddisfa entrambi i requisiti. Per ogni elemento nella lista delle transazioni, l’istruzione if controlla la truthiness di due espressioni:

  • I valori associati alla chiave "Success" in ogni dizionario sono True o False.
  • L’operatore maggiore o uguale in item["Price"] >= 100 restituisce anch’esso True o False.

Il libro Python e i cavi non soddisfano il requisito di prezzo perché sono sotto i 100 $. La macchina del caffè supera questa soglia, ma la transazione non è andata a buon fine, quindi è esclusa dalla stampa.

Torneremo su questo esempio del negozio online più avanti nel tutorial.

Nella sezione seguente, ci concentreremo sull’operatore or.

Python: l’operatore or

L’operatore logico OR nella logica booleana richiede due operandi. Valuta a vero se almeno uno degli operandi è vero:

Operazione

Valore in uscita

true OR true

true

true OR false

true

false OR true

true

false OR false

false

Possiamo ricreare questa tavola di verità usando l’operatore or di Python:

options = True, False
for a in options:
    for b in options:
        print(f"{a} or {b} gives {a or b}")
True or True gives True
True or False gives True
False or True gives True
False or False gives False

Possiamo anche riprendere l’esempio dei nomi visto prima, ma sostituire l’operatore and con or:

names = "James", "Bob", "David", "Jane", "Kate", "Mary"
for name in names:
    if len(name) < 5 or name[0] == "J":
        print(name)
James
Bob
Jane
Kate
Mary

L’istruzione if ora contiene un’espressione or. Di conseguenza, il ciclo for stampa tutti i nomi che hanno meno di cinque lettere oppure iniziano con la lettera "J". La stringa "Jane" soddisfa entrambi i requisiti. Gli altri nomi stampati soddisfano uno dei due.

Operatore or in Python: truthy e falsy

Anche l’operatore or considera valori truthy e falsy e non solo i booleani True e False. Vediamo alcuni esempi:

if 42 or [10, 20, 30]:
    print("At least one operand is truthy")
else:
    print("None of the operands is truthy")
At least one operand is truthy

Ora consideriamo questo esempio:

if 42 or []:
    print("At least one operand is truthy")
else:
    print("None of the operands is truthy")
At least one operand is truthy

E consideriamo anche quest’ultimo esempio:

if 0 or []:
    print("At least one operand is truthy")
else:
    print("None of the operands is truthy")
None of the operands is truthy

Nel primo esempio, l’intero 42 e la lista non vuota [10, 20, 30] sono truthy. Poiché l’operatore or richiede almeno un operando truthy, l’intera espressione valuta a truthy.

Nel secondo esempio, 42 è truthy ma la lista vuota [] è falsy in quanto sequenza vuota. Dal momento che uno dei due operandi è truthy, l’intera espressione con or valuta a truthy.

Nell’ultimo esempio, sia 0 sia [] sono falsy. Quindi, l’intera espressione valuta a falsy.

L’operatore or usa anche lo short-circuit nella valutazione dell’espressione per evitare valutazioni non necessarie. Vediamo alcuni esempi per illustrare il punto:

print(42 or [10, 20, 30])
print(42 or [])
print([] or 42)
print([] or 0)
42
42
42
0

Nel primo esempio, il primo operando è 42, che è truthy. Poiché or richiede solo un operando truthy per determinare la truthiness finale dell’intera espressione, questo primo operando viene restituito immediatamente. Il secondo operando non viene valutato perché il suo valore non influisce sul risultato finale. L’operatore or restituisce il primo operando, 42, non il booleano True. In Python, qualsiasi valore truthy ha lo stesso effetto del booleano True in contesti come le istruzioni if e while.

Nel secondo esempio, anche il primo operando è 42, e l’espressione restituisce questo intero anche se il secondo operando è falsy.

Nel terzo e nel quarto esempio, il primo operando è la lista vuota, che è falsy. Di conseguenza, in entrambi i casi viene restituito il secondo operando.

Esempio: il negozio online per programmatori

Riprendiamo le transazioni del negozio online che vende articoli ai programmatori. Ecco le quattro transazioni di esempio che usiamo in questo caso:

data = [
{"Item": "Python Book", "Price": 50, "Quantity": 1, "Success": True},
{"Item": "Coffee Machine", "Price": 125, "Quantity": 1, "Success": False},
{"Item": "Headphones", "Price": 250, "Quantity": 1, "Success": True},
{"Item": "Cables", "Price": 15.99, "Quantity": 3, "Success": True},
]

Devi individuare alcune transazioni da analizzare per capire meglio il comportamento dei clienti. Vuoi trovare le transazioni che o sono fallite oppure includono un articolo con prezzo inferiore a 75 $. Poiché hai due condizioni e ti basta che una transazione ne soddisfi almeno una, puoi usare l’operatore or:

for item in data:
    if item["Success"] == False or item["Price"] < 75:
        print(item)
{'Item': 'Python Book', 'Price': 50, 'Quantity': 1, 'Success': True}
{'Item': 'Coffee Machine', 'Price': 125, 'Quantity': 1, 'Success': False}
{'Item': 'Cables', 'Price': 15.99, 'Quantity': 3, 'Success': True}

Questo ciclo for mostra le righe che corrispondono ad almeno uno dei requisiti. Il libro Python e i cavi sono inclusi perché il loro prezzo è inferiore a 75 $. La macchina del caffè è inclusa perché la transazione non è andata a buon fine.

Esiste un altro modo per filtrare le transazioni non riuscite, che esploreremo nella sezione seguente.

Python: l’operatore not

L’operatore NOT differisce da AND e OR perché richiede un solo operando. NOT converte vero in falso e viceversa. Ecco la tavola di verità per NOT:

Operazione

Valore in uscita

NOT true

false

NOT false

true

Possiamo replicarlo usando l’operatore not di Python:

options = True, False
    for a in options:
        print(f"not {a} evaluates to {not a}")
not True evaluates to False
not False evaluates to True

Operatore not in Python: truthy e falsy

Come per and e or, l’operando usato con not non deve per forza essere un booleano. Poiché ogni oggetto è o truthy o falsy, qualsiasi oggetto può essere usato con not.

if not "python":
    print("The `if` statement evaluated as `True`")
else:
    print("The `if` statement evaluated as `False`")
The `if` statement evaluated as `False`

Guardiamo anche questo esempio:

if not "":
    print("The `if` statement evaluated as `True`")
else:
    print("The `if` statement evaluated as `False`")
The `if` statement evaluated as `True`

I valori truthy vengono convertiti in False con l’operatore not e i valori falsy vengono convertiti in True.

A differenza di and e or, l’operatore not restituisce sempre un oggetto booleano:

print(not "python")
print(not "")
False
True

Esempio: il negozio online per programmatori

Nelle sezioni precedenti abbiamo usato le transazioni di un negozio online. In questo esempio vogliamo mostrare tutte le transazioni non riuscite. Un’opzione è usare l’operatore di uguaglianza == per verificare se data["Success"] è uguale a False. Tuttavia, possiamo anche usare l’operatore not:

data = [
{"Item": "Python Book", "Price": 50, "Quantity": 1, "Success": True},
{"Item": "Coffee Machine", "Price": 125, "Quantity": 1, "Success": False},
{"Item": "Headphones", "Price": 250, "Quantity": 1, "Success": True},
{"Item": "Cables", "Price": 15.99, "Quantity": 3, "Success": True},
]
for item in data:
    if not item["Success"]:
        print(item)
{'Item': 'Coffee Machine', 'Price': 125, 'Quantity': 1, 'Success': False}

Poiché item["Success"] è uguale a False per le transazioni non riuscite, not item["Success"] restituisce True. Di conseguenza, il ciclo for stampa le transazioni non riuscite:

Nella sezione seguente, vedremo come combinare più operatori logici in un’unica espressione.

Python: precedenza degli operatori

Negli esempi visti finora, abbiamo usato un solo operatore logico per volta. In questa sezione, vedremo cosa succede quando combiniamo più operatori logici in un’unica espressione.

Python: and ha precedenza su or

Continueremo a lavorare sulle transazioni del negozio online usate in precedenza. Proviamo la seguente istruzione condizionale:

data = [
{"Item": "Python Book", "Price": 50, "Quantity": 1, "Success": True},
{"Item": "Coffee Machine", "Price": 125, "Quantity": 1, "Success": False},
{"Item": "Headphones", "Price": 250, "Quantity": 1, "Success": True},
{"Item": "Cables", "Price": 15.99, "Quantity": 3, "Success": True},
]
​
for item in data:
    if item["Price"] > 100 or item["Quantity"] > 2 and item["Success"]:
        print(item)
{'Item': 'Coffee Machine', 'Price': 125, 'Quantity': 1, 'Success': False}
{'Item': 'Headphones', 'Price': 250, 'Quantity': 1, 'Success': True}
{'Item': 'Cables', 'Price': 15.99, 'Quantity': 3, 'Success': True}

L’istruzione if contiene due operatori logici. Prima di vedere come Python gestisce questa espressione, guardiamo una traduzione in italiano dell’istruzione if: Se il prezzo dell’articolo è superiore a 100 $ oppure la quantità venduta è maggiore di due e la vendita è andata a buon fine, allora stampa l’articolo.

Questa frase è ambigua senza una punteggiatura più ricca e può creare confusione anche aggiungendo più virgole. Ad esempio, la transazione con la macchina del caffè dovrebbe essere inclusa? Il prezzo dell’articolo supera la soglia richiesta ma la transazione non è andata a buon fine.

Python risolve questa ambiguità assegnando all’operatore and una precedenza maggiore rispetto a or. Significa che l’espressione con and viene valutata per prima e il suo risultato viene usato nell’espressione con or.

Quindi, l’espressione item["Quantity"] > 2 and item["Success"] viene valutata per prima. Questa espressione restituisce un valore truthy solo per la transazione che include i cavi. Per gli altri articoli valuta a falsy.

Il valore dell’espressione and viene poi usato con l’operatore or. L’espressione or restituisce un valore truthy per qualsiasi articolo che restituisce truthy per l’espressione and—in questo caso solo la transazione con i cavi—e per gli articoli con prezzo superiore a 100 $. Ci sono due articoli con prezzo sopra la soglia: la macchina del caffè e le cuffie.

Python: parentesi e operatori logici

Tuttavia, cosa succede se ci servono transazioni con articoli dal prezzo superiore a 100 $ o con quantità superiore a due, ma vogliamo anche assicurarci che la transazione sia andata a buon fine? In questo caso, vogliamo che l’espressione or abbia precedenza su and, così da essere valutata per prima. Possiamo ottenerlo usando le parentesi attorno all’espressione or:

for item in data:
    if (item["Price"] > 100 or item["Quantity"] > 2) and item["Success"]:
        print(item)
{'Item': 'Headphones', 'Price': 250, 'Quantity': 1, 'Success': True}
{'Item': 'Cables', 'Price': 15.99, 'Quantity': 3, 'Success': True}

Le parentesi aggiuntive danno precedenza all’espressione or. La transazione della macchina del caffè non è più inclusa perché valuta a falsy per il secondo operando di and.

Python: not ha precedenza su and e or

L’operatore not ha precedenza su and e or. Quindi, not viene valutato prima degli altri due operatori logici.

Consideriamo la seguente istruzione if, che include sia not sia and:

for item in data:
    if not item["Success"] and item["Price"] > 100:
        print(item)
{'Item': 'Coffee Machine', 'Price': 125, 'Quantity': 1, 'Success': False}

Poiché not viene valutato per primo, questa espressione applica prima l’operatore not a item["Success"]. Il valore dell’espressione not viene poi usato come primo operando nell’espressione con and. Solo la voce relativa alla macchina del caffè soddisfa questa condizione—è l’unica transazione fallita con prezzo sopra i 100 $.

Possiamo però dare precedenza all’operatore and usando le parentesi:

for item in data:
    if not (item["Success"] and item["Price"] > 100):
        print(item)
{'Item': 'Python Book', 'Price': 50, 'Quantity': 1, 'Success': True}
{'Item': 'Coffee Machine', 'Price': 125, 'Quantity': 1, 'Success': False}
{'Item': 'Cables', 'Price': 15.99, 'Quantity': 3, 'Success': True}

In questo caso, l’espressione and viene valutata per prima. Solo la voce con le cuffie valuta a True perché è l’unica transazione riuscita con prezzo superiore a 100 $. Tuttavia, aggiungiamo un operatore not prima dell’espressione tra parentesi. Di conseguenza, il codice stampa le restanti tre transazioni.

In generale, se un’espressione diventa troppo complessa perché ha troppi operatori, è meglio spezzarla per renderla più leggibile.

Conclusione

Gli operatori logici and, or e not sono usati ampiamente in un’ampia gamma di applicazioni di programmazione e data science. Questi operatori replicano il comportamento degli operatori logici booleani AND, OR e NOT ampiamente usati in logica e matematica.

Tuttavia, gli operatori Python possono accettare qualsiasi oggetto e non solo valori booleani. Gli operatori and e or usano la valutazione short-circuit e restituiscono uno degli operandi come output.

Gli operatori logici di Python sono strumenti chiave per filtrare i dati, identificare caratteristiche nei set di dati e creare regole complesse per controllare il flusso di un programma. Se vuoi saperne di più, dai un’occhiata a questo career track di nove corsi: Data Analyst With Python.

Stephen Gruppetta

Autore

Stephen Gruppetta

Ho studiato Fisica e Matematica a livello UG presso l’Università di Malta. Poi mi sono trasferito a Londra e ho conseguito il dottorato in Fisica all’Imperial College. Ho lavorato su nuove tecniche ottiche per immagini della retina umana. Ora mi concentro sullo scrivere di Python, comunicare su Python e insegnare Python.

FAQ sugli operatori logici in Python

Posso usare l’operatore and per testare più condizioni in una volta?

Sì, puoi concatenare più condizioni usando l’operatore and. Per esempio: if x > 5 and x < 10 and x != 7.

Qual è la differenza tra l’operatore and e l’operatore AND bit per bit (&)?

L’operatore and esegue un’operazione AND logica su valori booleani, restituendo True solo se entrambi gli operandi sono True. L’operatore AND bit per bit (&) esegue invece un’operazione AND bitwise sulla rappresentazione binaria di valori interi.

Python ha gli operatori && e || come alcuni altri linguaggi?

No, Python usa le keyword and e or al posto dei simboli && e || per le operazioni logiche.

Argomenti

Correlato