Les conditionnelles
Prédire la valeur
Écris la valeur de l'expression demandée comme Python l'écrirait ('abc', True, 2.0), puis valide. Quand le champ est marqué « affiche », écris plutôt ce que le programme affiche. Si le programme s'arrête sur une erreur, écris erreur. Les valeurs changent à chaque essai.
Rappel d'ouverture (5 minutes, cours fermé)
Réponds sans rouvrir les pages précédentes, en écrivant tes réponses. Se tester est ce qui fixe les acquis ; relire ne le fait pas.
- Après
a = 3puisa = a + 2, que vauta? Dans quel ordre la machine fait-elle le calcul et le rangement ? - Écris la signature typée d'une fonction
est_majeurqui prend un âge entier et renvoie un booléen. - Avec \(a = 1\) et \(b = 0\), que vaut \(\overline{a.b}\) ? Que vaut \(\bar{a} + \bar{b}\) ?
Correction
avaut5. Le membre de droite est calculé d'abord (3 + 2), et le résultat est ensuite rangé dans la casea. Le=n'est pas une égalité mathématique.def est_majeur(age: int) -> bool:- \(a.b = 0\), donc \(\overline{a.b} = 1\). Et \(\bar{a} = 0\), \(\bar{b} = 1\), donc \(\bar{a} + \bar{b} = 1\). Les deux valent \(1\), et ce n'est pas un hasard : c'est la loi de De Morgan, que tu as utilisée pour câbler tes portes. Tu vas la retrouver dans les conditions de ce chapitre.
Pourquoi ? Décider.
Jusqu'ici, nos programmes exécutent les instructions les unes après les autres, toujours dans le même ordre. Mais un programme doit souvent choisir ce qu'il fait selon la situation : afficher « majeur » ou « mineur » selon l'âge, accepter ou refuser un mot de passe, calculer un tarif selon le client.
Une conditionnelle donne au programme ce pouvoir de décision. On la représente souvent par un diagramme d'activité : les losanges sont les questions que l'on se pose, les rectangles les actions à réaliser.
flowchart TD
A((Début)) --> B["Lire age et promo (o/n)"]
B --> C{"age < 0 ?"}
C -- Vrai --> X["Afficher: Age invalide"] --> Z(("Fin"))
C -- Faux --> D{"age < 12 ?"}
D -- Vrai --> T1["tarif = 5"] --> F{"Promo ?"}
D -- Faux --> E{"age < 18 ?"}
E -- Vrai --> T2["tarif = 7"] --> F
E -- Faux --> G{"age >= 65 ?"}
G -- Vrai --> T3["tarif = 6"] --> F
G -- Faux --> T4["tarif = 10"] --> F
F -- Vrai --> R1["tarif = max(0, tarif - 2)"] --> O["Afficher tarif"]
F -- Faux --> R2["tarif inchangé"] --> O
O --> Z
(Combien aurais-tu payé dans ce cinéma ? Tu coderas ce diagramme en exercice.)
SI ... ALORS : une seule branche
Conditionnelle à une branche
SI (il fait beau) ALORS (je mets mes lunettes de soleil).
« Il fait beau » est la condition. « Je mets mes lunettes » est le bloc d'instructions exécuté seulement si la condition est vraie.
En Python :
Le bloc d'instructions doit être indenté (touche tabulation).
Prédis avant d'exécuter
Sans lancer le code, écris ce qui s'affiche dans les deux cas : avec age = 20, puis avec age = 15. Combien de lignes chaque fois ?
Correction
Avec age = 20, trois lignes : « Vous êtes majeur. », « Bienvenue. », « Fin du programme. » Python évalue 20 >= 18, qui vaut True, entre dans le bloc indenté et exécute ses deux lignes, puis continue avec la ligne non indentée.
Avec age = 15, une seule ligne : « Fin du programme. » La condition 15 >= 18 vaut False, Python saute tout le bloc indenté et reprend juste après.
Ce qui décide de tout, ce n'est pas le if mais l'indentation : elle seule dit ce qui est sauté et ce qui ne l'est pas.
L'indentation définit le bloc
Ce sont les espaces en début de ligne qui disent ce qui est « à l'intérieur » du if. Une ligne réalignée à gauche n'en fait plus partie.
SI ... ALORS ... SINON : deux branches
Conditionnelle à deux branches
SI (il fait beau) ALORS (je mets mes lunettes) SINON (je prends mon parapluie).
age = int(input("Votre âge ? "))
if age >= 18:
print("Vous êtes majeur !")
else:
print("Vous êtes mineur !")
print("Au revoir !")
Exactement un des deux blocs s'exécute, jamais les deux, jamais aucun.
Les opérateurs de comparaison
Une condition se construit avec des comparaisons :
| Opérateur | Signification |
|---|---|
== |
égal à |
!= |
différent de |
< |
strictement inférieur à |
> |
strictement supérieur à |
<= |
inférieur ou égal à |
>= |
supérieur ou égal à |
Piège : == n'est pas =
=est l'affectation :age = 18range 18 dansage.==est le test d'égalité :age == 18vautTrueouFalse.
Dans une condition, on teste, donc on écrit ==. C'est une source de bugs très fréquente chez les débutants.
Exercices (deux branches)
- Parc. Il faut mesurer au moins 1m30 pour entrer. Demande la taille en cm et indique si l'accès est autorisé.
- Plus grand. Demande deux nombres et affiche le plus grand.
- Valeur absolue. Demande un nombre et affiche sa valeur absolue (sans
abs). - Mot de passe. Le mot de passe est
"azerty". Demande-le et indique si l'accès est autorisé.
Une condition est un booléen
Une comparaison comme 7 > 4 est une opération, au même titre que + ou *, sauf qu'elle ne renvoie pas un nombre mais un booléen : True ou False (le type booléen est présenté dans Les booléens, du nom du logicien George Boole).
Une condition est un calcul
Une condition est en réalité un calcul qui renvoie un booléen. Quand tu te demandes s'il fait beau, ton cerveau calcule vrai ou faux à partir de ce que voient tes yeux.
On peut donc stocker une condition dans une variable, puis l'utiliser :
Écrire if majeur, pas if majeur == True
Si majeur vaut True, alors majeur == True vaut aussi True ; s'il vaut False, majeur == True vaut False. Tester majeur ou majeur == True revient donc au même. On écrit simplement :
Exercice : type et valeur
On exécute ces lignes dans l'ordre. Donne le type et la valeur de chaque variable.
SINON SI : plusieurs branches (elif)
Pour plus de deux cas, on enchaîne avec elif (contraction de « else if »).
Le mécanisme caché : Python s'arrête au premier vrai
Python teste les conditions dans l'ordre. Dès qu'une est vraie, il exécute son bloc et ignore toutes les suivantes. Évaluer la condition d'un elif signifie donc que toutes les précédentes étaient fausses. Le else final ne sert que si aucune n'a été vraie.
L'ordre des elif compte
Avec note = 15 :
if note >= 10:
mention = "passable"
elif note >= 12:
mention = "assez bien"
elif note >= 14:
mention = "bien"
"passable" ! Car 15 >= 10 est vrai en premier, et Python s'arrête là. Il faut tester du cas le plus exigeant au moins exigeant.
Exercices (elif)
- Mention au bac. À partir d'une moyenne sur 20 :
[0;8)Recalé,[8;10)Rattrapage,[10;12)Sans mention,[12;14)Assez bien,[14;16)Bien,[16;18)Très bien,[18;20]Félicitations. - Année bissextile. Une année est bissextile si elle est multiple de 4 mais pas de 100, ou multiple de 400. Teste 2021, 2020, 1900, 2000.
Combiner les conditions : and, or, not
On combine des booléens avec and (et), or (ou, inclusif) et not (non). Les tables de vérité sont dans Les booléens. Ce sont de vraies opérations : elles prennent des booléens et renvoient un booléen.
Cela permet souvent de remplacer des conditions imbriquées par une seule, plus claire.
Le pass sanitaire : de l'imbriqué au booléen
On peut entrer si on est vacciné, ou, à défaut, si on a un test négatif.
Version imbriquée, lourde :
if vaccine:
print("Vous pouvez entrer")
else:
if test_negatif:
print("Vous pouvez entrer")
else:
print("Vous ne pouvez pas entrer")
Version elif, un peu mieux :
if vaccine:
print("Vous pouvez entrer")
elif test_negatif:
print("Vous pouvez entrer")
else:
print("Vous ne pouvez pas entrer")
Version booléenne, la plus claire :
Tester un encadrement
Pour vérifier qu'un nombre n est entre 4 et 8 inclus, il faut qu'il soit >= 4 et <= 8 :
Nier une condition : les lois de De Morgan
Tu as calculé sur les expressions booléennes dans le chapitre Logique booléenne, sans savoir encore à quoi cela servirait. C'est ici. Le cas le plus fréquent est la négation d'une condition composée, et c'est aussi celui où l'on se trompe le plus.
Reprends l'encadrement ci-dessus. Comment écrire « n n'est pas entre 4 et 8 » ?
# Correct, mais lourd
if not (n >= 4 and n <= 8):
print("hors de l'intervalle")
# Le même test, écrit directement
if n < 4 or n > 8:
print("hors de l'intervalle")
Le passage de l'un à l'autre suit une règle, et une seule :
Les lois de De Morgan
Pour nier une condition composée, on inverse l'opérateur et on nie chaque partie.
| En Python | En notation booléenne |
|---|---|
not (a and b) équivaut à not a or not b |
\(\overline{a.b} = \bar{a} + \bar{b}\) |
not (a or b) équivaut à not a and not b |
\(\overline{a+b} = \bar{a}.\bar{b}\) |
Le and devient or, le or devient and, et chaque morceau est nié. Si tu as un doute, dresse la table de vérité des deux expressions : elles ont la même colonne de résultat. C'est exactement ce que tu faisais en logique.
Piège : le or qui est toujours vrai
Tu veux tester que n n'est ni 4 ni 8. Beaucoup écrivent :
Prends n = 4 : n != 4 est faux, mais n != 8 est vrai, donc le or est vrai. Prends n = 8 : c'est l'inverse, et le or est encore vrai. Prends n'importe quel autre nombre : les deux sont vrais. Cette condition ne peut jamais être fausse.
L'erreur vient de la négation. La phrase de départ est « n est 4 ou 8 », soit n == 4 or n == 8. En la niant, De Morgan transforme le or en and :
Retiens la forme : quand tu nies une liste de possibilités, les or deviennent des and.
Prédis avant d'exécuter
Pour chacune de ces conditions, dis si elle est vraie ou fausse quand age = 20 et permis = False, avant de l'essayer.
c1 = not (age >= 18 and permis)
c2 = not age >= 18 or not permis
c3 = not (age < 18 or permis)
c4 = age >= 18 and not permis
Que remarques-tu en comparant c1 et c2 ? Et c3 et c4 ?
Correction
age >= 18 est vrai, permis est faux.
c1:not (vrai and faux)=not faux= Truec2:not vrai or not faux=faux or vrai= Truec3:not (faux or faux)=not faux= Truec4:vrai and not faux=vrai and vrai= True
c1 et c2 sont les deux formes de la même chose, par De Morgan. c3 et c4 aussi. Ce ne sont pas quatre conditions, mais deux conditions écrites chacune de deux façons. Vérifie-le en changeant les valeurs de age et permis : les couples resteront toujours d'accord.
Simplifier au lieu d'empiler
L'autre usage de l'algèbre booléenne est la simplification. Si tu obtiens une condition comme celle-ci :
elle se réduit à if vaccine:. En effet, si vaccine est vrai, le premier morceau suffit ; s'il est faux, le second l'est aussi puisqu'il commence par vaccine. C'est la règle \(x + x.y = x\), que tu as démontrée par le calcul en logique.
Une condition simplifiée n'est pas seulement plus courte : elle est plus facile à relire, donc plus facile à corriger.
Exercices (booléens)
- Triangle. Demande trois longueurs entières
a,b,c. Si elles ne peuvent pas former un triangle (chaque côté doit être inférieur à la somme des deux autres), affichepas un triangle. Sinon, afficheequilateral,isoceleouscalene. - Cinéma. Implémente en Python le calcul de tarif du diagramme d'activité du début de la page.
- Bissextile, version booléenne. Reprends l'année bissextile avec un seul calcul booléen.
Indice léger (triangle)
Il y a deux décisions successives, pas une seule : d'abord « est-ce un triangle ? », et seulement ensuite « lequel ? ». N'essaie pas de tout écrire dans un seul enchaînement de elif.
Indice plus précis (triangle)
La première décision est un if / else dont la condition combine trois comparaisons avec and. La seconde décision, dans le else, est un elif à trois branches : combien de côtés sont égaux ? Attention à l'ordre, l'équilatéral est le cas le plus exigeant.
Indice léger (cinéma)
Suis le diagramme dans l'ordre où il est dessiné : il te donne déjà la structure du programme. Chaque losange est un test, chaque rectangle une affectation.
Indice plus précis (cinéma)
Le diagramme se lit en deux temps. Un premier bloc if / elif / else fixe le tarif selon l'âge, du plus exigeant au moins exigeant. Puis, après ce bloc et une seule fois, un second if applique la promotion. Ne recopie pas la promotion dans chaque branche.
Projet : livre dont vous êtes le héros
Implémente l'histoire suivante avec des conditionnelles et des saisies utilisateur.
flowchart TD
A((Début)) --> C{Choisir la forêt ?}
C -- Vrai --> D[Cabane forêt]
D --> E{Frapper ?}
E -- Vrai --> K1[cle = True] --> H[Arrive à la grille]
E -- Faux --> L1[Échec : piège] --> Z(((Fin)))
H --> G{cle ?}
G -- Vrai --> V1[Victoire] --> Z
G -- Faux --> L2[Échec : grille fermée] --> Z
C -- Faux --> M[Entrée caverne]
M --> N{Torche ?}
N -- Vrai --> P[Avancer]
P --> Q{Courir ?}
Q -- Vrai --> V2[Victoire] --> Z
Q -- Faux --> L3[Échec : perdu] --> Z
N -- Faux --> L4[Échec : trou] --> Z
Une conditionnelle combinée à une boucle permet de filtrer ou de compter (par exemple : compter les 6 sur 1000 lancers de dé). On y viendra juste après, avec Les boucles.
Avec ce qu'on sait déjà : des fonctions qui décident
Tu sais écrire des fonctions : une conditionnelle se place maintenant dans leur corps, et chaque branche peut renvoyer sa propre valeur.
Automatismes
Écris la signature, la docstring puis le code de :
pair_ou_impair(n): renvoie"pair"ou"impair".plus_petit(a, b): renvoie le plus petit des deux entiers.
IMC
- Écris
imc(poids, taille)qui renvoie l'indice de masse corporelle (formule sur Wikipédia). - Écris un programme qui demande poids et taille, puis affiche l'IMC et un message d'interprétation.
- Affiche une réserve claire : cette information ne doit pas servir à un autodiagnostic, il faut préférer l'avis d'un médecin.
Indice léger
La question 1 et la question 2 ne demandent pas la même chose. La fonction calcule et renvoie, elle n'affiche rien et ne demande rien à l'utilisateur. Tout ce qui est saisie et affichage se passe en dehors d'elle.
Indice plus précis
def imc(poids: float, taille: float) -> float: renvoie poids / (taille * taille), avec la taille en mètres. Le programme de la question 2 appelle cette fonction, range le résultat dans une variable, puis enchaîne des elif sur cette variable. Si tu as mis un print dans imc, relis le piège return contre print.
Point d'étape : où en es-tu vraiment ?
Ce bloc (variables, entiers, chaînes, conditionnelles) est le socle de tout le reste de l'année. Il vaut donc la peine de savoir maintenant, et pas en février, ce qui est acquis et ce qui ne l'est pas.
Vérification individuelle (15 minutes, seul, cours fermé)
À faire seul, sans aide et sans IA. Ce n'est pas noté : c'est un instrument de mesure, et il ne sert que si tu ne triches pas avec toi-même.
1. Lire. Que s'affiche-t-il ?
x = 7
y = x
x = x + 3
if y > 5 and x > 5:
print("les deux")
elif y > 5:
print("y seul")
else:
print("aucun")
print(x, y)
2. Compléter. Remplis les trous pour que le programme affiche "cher" si le prix dépasse 100, "correct" entre 50 et 100 inclus, et "bon marché" en dessous.
prix = int(input("Prix ? "))
if ...:
print("cher")
elif ...:
print("correct")
else:
print("bon marché")
3. Écrire. Depuis zéro : demande une année et affiche si elle est bissextile (multiple de 4 mais pas de 100, ou multiple de 400).
Correction
1. les deux puis 10 7. Le point délicat est y = x : il a copié la valeur 7 à cet instant, et x = x + 3 ne l'a pas suivi.
2. if prix > 100: puis elif prix >= 50:. L'ordre compte : le elif n'est atteint que si le premier test est faux, donc il est inutile d'y réécrire prix <= 100.
3.
Comment lire ton résultat
Les trois questions ne mesurent pas la même chose, et rater la troisième en réussissant la première n'est pas un signe de faiblesse. Lire du code, le compléter et l'écrire de zéro sont trois compétences distinctes, qui se travaillent séparément.
- Tu réussis les trois : passe à la suite.
- Tu réussis 1 et 2 mais pas 3 : tu comprends le mécanisme, il te manque la mise en route. Refais des exercices d'écriture courts, pas de la relecture.
- Tu rates la 1 : reprends le traçage avant tout le reste. Écrire du code qu'on ne sait pas lire ne mène nulle part.
Ce que ce point d'étape dit, et ce qu'il ne dit pas
En programmation, réussir un concept rend le suivant plus facile, et le rater le rend plus difficile : l'écart entre deux élèves se creuse par enchaînement, pas parce que l'un aurait un don et l'autre non. C'est justement pour cela qu'on mesure tôt, quand un rattrapage coûte encore une heure et pas un trimestre. Un résultat faible aujourd'hui est une information sur ce qu'il faut retravailler, rien d'autre.