Retour au cours

booléens et comparaisons : opérateurs de comparaison et logiques

dans cette leçon, vous apprenez à comparer proprement des valeurs et à raisonner avec la logique booléenne en python. vous verrez la vérité des valeurs (truthiness), les opérateurs and, or, not, les comparaisons chaînées (0 < x < 10), l’identité (is) et l’appartenance (in), ainsi que les pièges courants.

objectifs

  • utiliser == != < <= > >=, in, is
  • raisonner avec and, or, not et le court-circuit (short-circuit)
  • écrire des comparaisons chaînées
  • faire la différence entre égalité et identité
  • éviter les erreurs avec None, NaN, et la vérité des valeurs

égalité, ordre, appartenance

5 == 5            # True
5 != 3            # True
3 < 5 <= 5        # True  (chaînage équivaut à 3 < 5 and 5 <= 5)

"a" < "b"         # True  (ordre unicode)
"py" in "python"  # True
2 in [1, 2, 3]    # True
"z" not in "abc"  # True

égalité vs identité

== compare le contenu. is compare l’identité (même objet en mémoire).

a = [1, 2]
b = [1, 2]
a == b     # True  (même contenu)
a is b     # False (deux listes distinctes)

x = None
x is None  # recommandé
x == None  # à éviter

ne testez pas if flag is True:. préférez if flag:.

vérité des valeurs (truthiness)

sont considérés faux : False, None, 0, 0.0, "", [], {}, set(). tout le reste est vrai.

if []:
    print("jamais")
else:
    print("liste vide")  # s'affiche

opérateurs logiques et court-circuit

  • A and B évalue A; si A est falsy, renvoie A, sinon évalue et renvoie B
  • A or B évalue A; si A est truthy, renvoie A, sinon renvoie B
"" or "fallback"       # "fallback"
"alex" or "fallback"   # "alex"
0 and 99               # 0
10 and 99              # 99

attention : and/or renvoient une valeur, pas forcément True/False. utile pour les valeurs par défaut :

username = env_user or input("nom ? ")

not inverse la vérité d’une expression complète :

not (3 < 2)   # True

précédence pratique

les comparaisons sont évaluées avant not, puis and, puis or. utilisez des parenthèses si un doute subsiste.

not 2 == 2 or 0   # False
# interprété comme: (not (2 == 2)) or 0  -> (not True) or 0 -> False or 0 -> 0 (falsy)

chaîner des comparaisons

évalue chaque opérande une seule fois, plus lisible et sûr :

x = 7
0 < x < 10     # True
x == y == 0    # True si x et y valent 0

flottants, NaN et comparaisons

NaN n’est égal à rien, même pas à lui-même.

import math
nan = float("nan")
nan == nan           # False
math.isnan(nan)      # True  (à utiliser)

pour comparer des float, préférez math.isclose(a, b).

comparaisons sur séquences

les séquences sont comparées lexicographiquement (élément par élément).

[1, 2, 10] < [1, 3]    # True (compare 1==1, 2 < 3)
(1, 2) < (1, 2, 0)     # True (préfixe plus court)

motifs utiles

# vérifier présence et non-vide
def has_name(d: dict) -> bool:
    return bool(d.get("name"))

# bornes inclusives
def in_range_inclusive(x: int, lo: int, hi: int) -> bool:
    return lo <= x <= hi

# value par défaut si vide
def coalesce(value, default):
    return value or default

# guard clause
def divide(a: float, b: float) -> float | None:
    if not b:
        return None
    return a / b

pièges courants

  • is au lieu de == pour comparer du texte ou des nombres
  • if value is True (testez if value:)
  • oublier que and/or renvoient une valeur (peut surprendre dans un print)
  • comparer des floats avec == (utiliser math.isclose)
  • not a == b est bien not (a == b) (les comparaisons s’évaluent avant not)
  • "10" < "2" est True car comparaison lexicographique (strings), pas numérique

mini exemples exécutables

# filtrer des noms valides
names = ["", "ana", None, "bob"]
valid = [n for n in names if n and n.strip()]
print(valid)  # ["ana", "bob"]
# sélection avec or / and
user = ""
current = user or "guest"
loud = current and current.upper()
print(current, loud)  # "guest", "GUEST"
# chaîne de comparaisons
temp = 22
print(18 <= temp <= 26)  # True
# piège des floats
from math import isclose
print(isclose(0.1 + 0.2, 0.3))  # True
# identité vs égalité
a = [1, 2, 3]
b = a
c = [1, 2, 3]
print(a == b, a is b)  # True True
print(a == c, a is c)  # True False

exercices

  1. règles d’accès écrivez can_access(age, is_member) qui renvoie True si age >= 18 ou si is_member est True et age >= 16. testez plusieurs cas.

  2. valeur par défaut implémentez safe_title(s) qui retourne s.strip().title() si s est non vide, sinon "inconnu", sans if explicite (utilisez and/or).

  3. borne de validité écrivez is_valid_score(x) qui renvoie True si 0 <= x <= 100 et False sinon. ajoutez un test qui rejette None proprement.

  4. recherche robuste fonction contains_ignore_case(haystack, needle) qui retourne True si needle se trouve dans haystack en ignorant la casse et les accents (normalisez en NFC).

  5. tri lexicographique expliquez en une phrase pourquoi ["é", "e"] trié donne souvent ["e", "é"]. montrez le résultat avec sorted().

dépannage

  • résultat inattendu avec and/or → souvenez-vous qu’ils renvoient une valeur, pas un bool strict.
  • comparaison qui lève typeerror (ex: 3 < "3") → ne comparez pas des types hétérogènes.
  • tests avec None → utilisez is None / is not None.
  • flottants “égaux” visuellement mais == False → utilisez math.isclose.