Menu

and, or et not en Python : opérateurs logiques, court-circuit et valeurs truthy

Comment fonctionnent les opérateurs and, or et not de Python : tables de vérité, valeurs truthy et falsy, évaluation en court-circuit, pourquoi and/or renvoient l'un de leurs opérandes, priorité, et and/or face à & et |.

Cette page contient des éditeurs exécutables - modifiez, exécutez et voyez la sortie instantanément.

Trois mots au lieu de symboles

Les opérateurs logiques de Python sont les mots anglais and, or et not. D'autres langages les écrivent &&, || et !. En Python, && et || provoquent une SyntaxError, et ! n'apparaît que dans != (« différent de »).

Avec True et False, les règles sont celles que tu attends :

aba and ba or bnot a
TrueTrueTrueTrueFalse
TrueFalseFalseTrueFalse
FalseTrueFalseTrueTrue
FalseFalseFalseFalseTrue

and exige que les deux côtés soient vrais. or en exige au moins un. not prend une seule valeur et l'inverse.

Dans du vrai code, les côtés sont en général des comparaisons, et le résultat alimente un if ou un while :

Sortie :

eligible
standard ticket

Cela suffit pour la plupart des conditions. La suite de cette page explique ce que font ces opérateurs avec des valeurs qui ne sont ni True ni False, et les règles qui décident quel côté d'une expression s'exécute.

Valeurs truthy et falsy

and, or et not acceptent n'importe quelle valeur, pas seulement des booléens. Python décide si une valeur compte comme vraie selon sa valeur de vérité. Ces valeurs sont falsy :

  • False et None
  • le zéro de tout type numérique : 0, 0.0
  • les conteneurs et chaînes vides : "", [], (), {}, set(), range(0)

Tout le reste est truthy, y compris "0", "False", [0] et -1. Tu peux voir comment Python classe une valeur avec bool() :

Sortie :

0 False
1 True
-1 True
'' False
'0' True
[] False
[0] True
None False
0.0 False

La chaîne "0" est truthy parce que c'est une chaîne non vide. Ce cas piège ceux qui lisent des nombres depuis une saisie et les testent avant de les convertir. La page sur les nombres et les booléens explique le lien entre bool et int.

and et or renvoient un opérande

C'est là que Python diffère de la plupart des langages. and et or ne produisent pas un nouveau True ou False. Ils renvoient l'une des deux valeurs que tu leur as données :

  • x or y renvoie x si x est truthy, sinon il renvoie y.
  • x and y renvoie x si x est falsy, sinon il renvoie y.

Quand les deux opérandes sont des booléens, « renvoyer un opérande » et « renvoyer un booléen » reviennent au même, c'est pourquoi la différence passe inaperçue jusqu'à ce que tu mélanges d'autres types.

not est l'exception : il renvoie toujours True ou False.

Si tu as besoin d'un vrai booléen à partir d'une expression and/or, par exemple pour le stocker ou le renvoyer depuis une fonction censée renvoyer un bool, entoure-la de bool() :

Évaluation en court-circuit

Python évalue and et or de gauche à droite et s'arrête dès que la réponse est connue :

  • and s'arrête à la première valeur falsy, parce que rien après elle ne peut rendre l'expression entière vraie.
  • or s'arrête à la première valeur truthy, parce que rien après elle ne peut rendre l'expression entière fausse.

Le côté ignoré n'est pas exécuté du tout. Tu peux l'observer avec des fonctions qui affichent un message quand on les appelle :

Sortie :

and:
  checking A
False
or:
  checking A
True

B n'est vérifié dans aucun des deux cas. C'est le court-circuit qui rend les conditions de garde sûres. La seconde moitié de chaque condition ci-dessous planterait toute seule, mais elle ne s'exécute qu'une fois que la première moitié a écarté le mauvais cas :

Place le test peu coûteux ou protecteur en premier. Inverser l'ordre, user.startswith("admin") and user is not None, lève AttributeError quand user vaut None.

Motifs bâtis sur or et and

Comme or renvoie son premier opérande truthy, il donne une valeur par défaut en une ligne :

Sortie :

Hello, Ada!
Hello, guest!
Hello, guest!

Le piège, c'est que or remplace toutes les valeurs falsy, pas seulement None. Si 0, "" ou [] est une entrée légitime, or la jettera :

Utilise x if x is not None else default quand zéro ou vide est une valeur valide. La page sur if/else présente cette expression conditionnelle.

and a un motif correspondant : « utilise cette valeur seulement si la première est définie ». Il est moins courant et souvent plus clair sous forme de if, alors ne t'en sers qu'avec parcimonie :

Priorité : not, puis and, puis or

Quand une expression mélange les trois, Python applique d'abord not, puis and, puis or. Les comparaisons comme ==, < et in s'appliquent avant les trois.

a or b and c et (a or b) and c donnent des réponses différentes avec les mêmes valeurs, donc une condition mixte devrait porter des parenthèses même quand l'ordre par défaut se trouve être le bon. Elles ne coûtent rien et évitent la question au prochain lecteur.

and/or face à &/|

& et | ressemblent à and et or et donnent parfois la même réponse, mais ce sont des opérateurs différents.

  • and et or testent la valeur de vérité, court-circuitent et renvoient l'un des opérandes.
  • & et | sont des opérateurs bit à bit. Sur des entiers, ils combinent les bits des deux nombres. Sur des ensembles, ils signifient intersection et union. Sur True et False, ils renvoient un booléen. Ils ne court-circuitent jamais : les deux côtés sont toujours évalués.

Les opérateurs bit à bit ont aussi une priorité plus forte que les comparaisons, ce qui transforme une condition écrite avec & en tout autre chose :

1 & y vaut 1 & 5, soit 1, donc la ligne du milieu devient la chaîne 5 > 1 > 1, et 1 > 1 est faux. En Python ordinaire, utilise and, or et not pour les conditions.

Le seul endroit où &, | et ~ sont corrects dans des conditions, c'est NumPy et pandas. Un tableau contient de nombreuses valeurs, il n'a donc pas de valeur de vérité unique, et and lève ValueError: The truth value of an array ... is ambiguous. Ces bibliothèques redéfinissent & et | pour qu'ils agissent élément par élément, c'est pourquoi les filtres pandas ressemblent à df[(df.age > 18) & (df.country == "CA")], avec des parenthèses autour de chaque comparaison pour la raison de priorité vue plus haut.

any() et all() : and et or sur une liste

Pour combiner toute une séquence de conditions, utilise les fonctions intégrées all() (un and sur tous les éléments) et any() (un or sur tous les éléments). Les deux court-circuitent de la même façon :

Contrairement à and et or, any() et all() renvoient toujours un booléen.

Erreurs courantes

Comparer une variable à plusieurs valeurs avec or. Cette condition est toujours vraie :

Python lit la première condition comme (color == "red") or "blue". La comparaison vaut False, donc or renvoie "blue", une chaîne non vide, qui est truthy. Répète la comparaison des deux côtés, ou mieux, teste l'appartenance avec in.

Écrire && ou ||. Les deux provoquent une SyntaxError. Utilise and et or.

Attendre un booléen de and/or. x = a or b stocke a ou b lui-même. C'est souvent ce que tu veux, mais si une fonction doit renvoyer True ou False, convertis avec bool().

Compter sur la priorité dans les conditions mixtes. a or b and c est légal et bien défini, mais ajoute des parenthèses pour que personne n'ait à se souvenir de la règle.

Questions fréquentes

Que fait l'opérateur and en Python ?

a and b n'est vrai que si les deux côtés sont vrais. Python évalue a en premier ; si a est falsy, il renvoie a sans regarder b, sinon il renvoie b. Avec de simples booléens, on obtient le résultat habituel : True and False vaut False.

Pourquoi 0 or 5 renvoie 5 et non True ?

or et and renvoient l'un de leurs opérandes, pas un nouveau booléen. x or y renvoie x si x est truthy, sinon y. 0 est falsy, donc 0 or 5 renvoie 5. Entoure l'expression de bool() si tu as besoin d'un vrai True ou False.

Quelle est la différence entre and et & en Python ?

and est un opérateur logique : il teste la valeur de vérité et court-circuite. & est un opérateur bit à bit : sur des entiers il combine les bits (6 & 3 vaut 2), sur des ensembles il calcule l'intersection, et il évalue toujours les deux côtés. Utilise and dans les conditions if. L'exception, ce sont NumPy et pandas, où & est le « et » élément par élément.

Lequel s'exécute en premier en Python, and ou or ?

not a la priorité la plus forte, puis and, puis or. Donc a or b and c signifie a or (b and c), et not a or b signifie (not a) or b. Les comparaisons comme == et < ont une priorité plus forte que les trois.

Peut-on utiliser && et || en Python ?

Non. && et || provoquent une SyntaxError en Python. Les opérateurs logiques sont les mots and, or et not. Un seul & ou | est valide mais signifie autre chose (le et/ou bit à bit).

Coddy programming languages illustration

Apprendre à coder avec Coddy

COMMENCER