On va s’attaquer pour cette leçon à un nouveau type de données. Il permet d’effectuer des opérations logiques. Il s’agit des booléens (bool
en python).
Il n’y en en fait que deux exemplaires, VRAI et FAUX ou en python:
>>> True
True
>>> False
False
>>> type(True)
<class 'bool'>
Noter qu’il n’y a qu’une seule façon valide de les écrire!
>>> false
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'false' is not defined
>>> TRUE
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'TRUE' is not defined
On peut combiner plusieurs booléens de trois manières distinctes.
La négation via not
>>> not True
False
>>> not False
True
La conjonction via and
>>> False and False
False
>>> False and True
False
>>> True and False
False
>>> True and True
True
Elle renvoie True
lorsque toutes les opérandes sont True
.
La disjonction via or
>>> False or False
False
>>> False or True
True
>>> True or False
True
>>> True or True
True
Elle renvoie True
lorsqu’au moins une des opérandes est True
.
Notez que les deux derniers opérateurs se généralisent à des conteneurs de booléens via les fonction any
et all
.
>>> vrais = (True, True, True)
>>> any(vrais)
True
>>> all(vrais)
True
>>> faux = (False, False, False)
>>> any(faux)
False
>>> all(faux)
False
>>> mixte = (False, True, False)
>>> all(mixte)
False
>>> any(mixte)
True
L’intérêt des booléens est de permettre de raisonner suivant que certains propriétés sont vraies ou fausses. On produit des booléens via des opérateurs de comparaisons.
Le test d’égalité via ==
permet de savoir si deux objets ont même valeurs.(ATTENTION =
est réservé à l’affectation!)
>>> x = 123456789
>>> y = 123456789
>>> z = 987654321
>>> x == y
True
>>> x == z
False
REMARQUE deux séquences (tuple
pour l’instant mais list
d’ici peu) sont égales si toutes leurs valeurs le sont (et à la même position)
>>> (1, 2) == (1, 2)
True
>>> (1, 2) == (2, 1)
False
>>> (1, 2, 3) == (1, 2)
False
Pour tester au contraire la différence de valeurs, on peut utiliser la négation not
ou l’opérateur !=
>>> x = 123456789
>>> y = 123456789
>>> z = 987654321
>>> not (x == y)
False
>>> x != y
False
>>> not (x == z)
True
>>> x != z
True
Comme on l’a déjà vu plusieurs fois, en python on fait la différence entre l’égalité (qui concerne la valeur de l’objet) et l’identité (qui concerne l’objet lui même). Pour tester l’identité on utilise is
>>> x = 123456789
>>> y = x
>>> z = 123456789
>>> x == y
True
>>> x == z
True
>>> x is y
True
>>> x is z
False
REMARQUE lorsque on veut nier l’identité on peut utiliser is not
qui se lit plus naturellement que l’utilisation de la négation en tête:
>>> x = 123456789
>>> y = x
>>> z = 123456789
>>> not (x is y)
False
>>> not (x is z)
True
>>> x is not y
False
>>> x is not y
False
On peut comparer la grandeur des nombres via les opérateurs strictement plus petit et strictement plus grand:
>>> 1 < 2
True
>>> 2 < 1
False
>>> 1 > 2
False
>>> 2 > 1
True
Les opérateurs de comparaison relatifs sont <=
et >=
(le signe =
vient en deuxième car on dit ou égal en second)
>>> 1 < 1
False
>>> 1 <= 1
True
>>> 1 >= 1
True
REMARQUE pour les séquences on utilise l’ordre dit lexicographique, c’est à dire qu’on fait les comparaisons des valeurs de gauche à droite. Plus succinctement les séquences sont ordonnées comme leur première composante non égale!
>>> (1, 2) < (3, 0)
True
>>> (1, 2) > (1, 1)
True
tuples
sont 1
et 3
qui sont dans l’ordre demandé, on ne regarde pas la suite et l’expression évalue à True
.1
et 1
, on va comparer les secondes. Comme 2
et 1
sont dans l’ordre demandé, l’expression évalue à True
.ATTENTION les str
sont elles aussi comparables via l’ordre lexicographique (et pas par leurs longueurs), mais cela permet juste de ramener la comparaison caractère par caractère. En première approche on peut utiliser l’ordre alphabétique pour analyser la situation.
>>> "a" < "b"
True
>>> "d" < "z"
True
>>> "f" < "b"
False
En fait la situation est plus délicate, ce qui est réellement comparé est l’unicode correspondant aux caractères (qu’on avait vu via l’échappement \uXXXX
), cela rend certaines comparaisons peu intuitives (on utilisera donc avec modération!)
>>> "." < "a"
True
>>> "A" < "a"
True
Notez qu’on peut comprendre un peu mieux ce qui se passe en utilise la fonction ord
pour récupérer l’unicode correspondant:
>>> ord(".")
46
>>> ord("a")
97
>>> ord("A")
65
not (x and y)
et (not x) or (not y)
pour toutes les valeurs possibles (booléennes) de x
, y
et z
.x and (y or z)
et (x and y) or (x and z)
pour toutes les valeurs possibles (booléennes) de x
, y
et z
.E1 or E2
(où E1
et E2
sont des expressions booléennes) entre les deux scénarios suivants:
E1
puis on évalue E2
et seulement ensuite on applique or
.E1
, si on a True
on n’évalue pas E2
mais on renvoie directement True
(puisqu’après tout True and
n’importe quoi fait toujours True
)On pourra essayer
>>> help("BOOLEAN")
et
>>> help("COMPARISON")
On utilise le code
>>> x, y = True, True
>>> (not (x and y)) == ((not x) or (not y))
True
>>> x, y = True, False
>>> (not (x and y)) == ((not x) or (not y))
True
>>> x, y = False, True
>>> (not (x and y)) == ((not x) or (not y))
True
>>> x, y = False, False
>>> (not (x and y)) == ((not x) or (not y))
True
On voit que les deux expressions évaluent toujours identiquement, on a le même résultat en échangeant or
et and
.
On code de manière laborieuse (là encore on appréciera les boucles!)
>>> x, y, z = True, True, True
>>> (x and (y or z)) == ((x and y) or (x and z))
True
>>> x, y, z = True, True, False
>>> (x and (y or z)) == ((x and y) or (x and z))
True
>>> x, y, z = True, False, True
>>> (x and (y or z)) == ((x and y) or (x and z))
True
>>> x, y, z = True, False, False
>>> (x and (y or z)) == ((x and y) or (x and z))
True
>>> x, y, z = False, True, True
>>> (x and (y or z)) == ((x and y) or (x and z))
True
>>> x, y, z = False, True, False
>>> (x and (y or z)) == ((x and y) or (x and z))
True
>>> x, y, z = False, False, True
>>> (x and (y or z)) == ((x and y) or (x and z))
True
>>> x, y, z = False, False, False
>>> (x and (y or z)) == ((x and y) or (x and z))
True
On peut constater que les deux expressions booléennes sont égales indépendamment des valeurs des variables booléennes. On dit qu’on a distributivité, notez que si l’on substitue and
et or
le résultat est encore vrai. On pourra aller regarder ici pour plus d’informations sur les deux premières questions.
Ici on va choisir pour E2
une expression dont l’évaluation fait planter python.
>>> (12 / 0) != 5
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: division by zero
>>> (1 == 1) or (12 / 0 != 5)
True
On constate que c’est le deuxième scénario qui a lieu, on dit qu’on a une évaluation fainéante. Le même phénomène a lieu pour E1 and E2
si E1
évalue à False
. On signale ce phénomène car il est utilisée de manière passablement astucieuses dans différentes situations. (et malheureusement assez impénétrable pour qui ne connait pas le phénomène)