Leçon 02-1 — if, elif, else : décider

1. Objectif

À la fin de cette leçon tu sauras : écrire un programme qui exécute des lignes différentes selon une condition, avec if, elif et else ; comparer des valeurs avec ==, !=, <, <=, >, >= ; expliquer pourquoi = et == sont deux choses totalement différentes ; et indenter correctement des blocs, y compris imbriqués.

2. Pourquoi c'est important

Jusqu'ici, tes programmes exécutaient toutes leurs lignes, de haut en bas, à chaque fois. Un vrai programme décide : afficher « Majeur » ou « Mineur », accepter ou refuser un mot de passe, appliquer tel tarif ou tel autre. Le if est la première structure de contrôle — TOUT le reste du niveau 2 (et les boucles, et les fonctions du niveau 4) repose sur des conditions. C'est aussi ici qu'on rencontre l'indentation comme syntaxe : en Python, les espaces en début de ligne changent le sens du programme.

3. Explication simple

Un if se lit comme une phrase : « SI la condition est vraie, fais ceci ; SINON, fais cela ».

age = 17
if age >= 18:
    print("Majeur")
else:
    print("Mineur")
print("Fin du programme")

Sortie :

Mineur
Fin du programme

Quatre choses à voir sur ce squelette :

  1. La condition (age >= 18) est une expression qui vaut True ou False (un bool, vu en 01-2).
  2. Les deux-points : en fin de ligne annoncent un bloc. Obligatoires.
  3. Le bloc indenté (décalé de 4 espaces) : c'est ce qui est exécuté si la condition est vraie. L'indentation N'EST PAS décorative : elle dit à Python « ces lignes appartiennent au if ».
  4. La dernière ligne, non indentée, est hors du if : elle s'exécute toujours, quelle que soit la condition.

Pour comparer, tu disposes de six opérateurs :

OpérateurSensExemple vrai
==égal à5 == 5
!=différent de5 != 3
< / <=strictement inférieur / inférieur ou égal3 < 5, 5 <= 5
> / >=strictement supérieur / supérieur ou égal5 > 3, 5 >= 5

Le point crucial de toute la leçon : = assigne (colle une étiquette, leçon 01-1), == compare (pose une question, réponse True/False). age = 18 donne la valeur 18 à age ; age == 18 demande « est-ce que age vaut 18 ? » sans rien modifier.

4. Explication approfondie

a) elif : la chaîne de décisions. Quand il y a plus de deux cas, on enchaîne : ifelifelifelse. Python descend la chaîne et exécute le premier bloc dont la condition est vraie — puis saute tout le reste, même si une condition plus bas aurait aussi été vraie. Le else final (sans condition) attrape tous les cas restants ; il est facultatif.

Conséquence directe : l'ordre des elif est une décision de conception. Si tu testes score >= 50 avant score >= 90, un score de 95 s'arrête à la première condition vraie et affiche « Passable ». Pas d'erreur, juste un programme faux — on le verra en section 6.

b) L'indentation, précisément. La convention Python (universelle) : 4 espaces par niveau. VS Code les insère quand tu appuies sur Tab. Règles :

c) Conditions imbriquées. Un if peut contenir un autre if : le bloc intérieur est indenté de 8 espaces. C'est légal et parfois le plus lisible (« d'abord vérifier l'âge, PUIS le billet »). Mais au-delà de deux niveaux, le code devient pénible à lire — la leçon 02-2 (and, or) te donnera l'outil pour aplatir la plupart des imbrications.

d) Comparer des types différents — deux comportements à connaître.

print(3 == 3.0)    # True   : int et float comparent leurs VALEURS
print("3" == 3)    # False  : str et int ne sont JAMAIS égaux — sans erreur !

== entre types incompatibles ne plante pas : il répond tranquillement False. C'est le bug silencieux emblématique du niveau : input() renvoie "5", et "5" == 5 vaut False pour toujours. En revanche <, >, <=, >= entre une str et un int plantent (TypeError) — Python ne sait pas ordonner un texte et un nombre. Retiens : égalité = False silencieux ; ordre = TypeError bruyant.

e) Le chaînage, spécialité Python. 2 < 3 <= 3 est légal et vaut True : Python le lit comme « 2 < 3 ET 3 <= 3 ». Très pratique pour les intervalles (0 <= note <= 20). ⏩ Le and sous-jacent est le sujet de la leçon 02-2.

Difficulté honnête : la syntaxe de cette leçon s'apprend en une session. Ce qui prend du temps, c'est (1) le réflexe == vs =, (2) l'indentation qui change le sens sans message d'erreur, (3) l'ordre des elif. Les trois reviennent en force dans la leçon 02-5 (erreurs de logique) — considère cette leçon-ci comme la pose des fondations.

5. Exemples commentés

Exemple 1 — if/else minimal (celui de la section 3 — tape-le vraiment).

Exemple 2 — une chaîne elif bien ordonnée

score = 72
if score >= 90:
    print("Excellent")
elif score >= 70:          # testé seulement si score < 90
    print("Bien")
elif score >= 50:          # testé seulement si score < 70
    print("Passable")
else:                      # tous les cas restants : score < 50
    print("Echoue")

Sortie : Bien. Les seuils sont testés du plus haut au plus bas : chaque elif sait que les conditions précédentes étaient fausses, donc pas besoin d'écrire 70 <= score < 90 — le < 90 est garanti par la position.

Exemple 3 — une comparaison est une valeur comme une autre

age = 20
is_adult = age >= 18       # la droite est évaluée d'abord (True), puis assignée
print(is_adult)            # True
print(type(is_adult))      # <class 'bool'>

On peut stocker le résultat d'une comparaison dans une variable, l'afficher, la réutiliser dans un if (if is_adult:). Une condition n'a rien de magique : c'est une expression qui produit un bool.

Exemple 4 — condition sur une saisie utilisateur

answer = int(input("Combien font 2 + 2 ? "))   # int() : réflexe de la 01-2 !
if answer == 4:
    print("Correct !")
else:
    print(f"Non : tu as répondu {answer}")

Session (l'utilisateur tape 5) :

Combien font 2 + 2 ? 5
Non : tu as répondu 5

Sans le int(), la comparaison "4" == 4 serait toujours fausse — voir section 6.

Exemple 5 — conditions imbriquées

age = 25
has_ticket = True

if age >= 18:
    if has_ticket:              # testé SEULEMENT si age >= 18
        print("Entree autorisee")
    else:                       # cet else appartient au if INTÉRIEUR
        print("Va acheter un billet")
else:                           # celui-ci au if EXTÉRIEUR (même indentation)
    print("Interdit aux mineurs")

Sortie : Entree autorisee. Un else s'accroche au if qui a la même indentation que lui. Décale-le, et le programme change de sens (⏩ démonté en détail en 02-5).

6. Erreurs fréquentes

1) = au lieu de == dans la condition

age = 18
if age = 18:
    print("majeur")
# SyntaxError: invalid syntax. Maybe you meant '==' or ':=' instead of '='?

Python te sauve : assigner dans un if est interdit, et le message suggère même la correction. Grave le réflexe : = assigne, == compare. (L'inverse — age == 18 seul sur une ligne à la place d'une assignation — est légal et ne fait RIEN : la comparaison est calculée puis jetée. Bug silencieux.)

2) Oublier les deux-points

x = 5
if x == 5
    print("ok")
# SyntaxError: expected ':'

Le message dit exactement quoi, et le ^ pointe la fin de la ligne fautive. if, elif, else : deux-points obligatoires, toujours.

3) Oublier d'indenter le bloc

x = 5
if x == 5:
print("ok")
# IndentationError: expected an indented block after 'if' statement on line 2

Après un :, Python exige au moins une ligne indentée. Le message te donne la ligne du if orphelin.

4) Indenter au hasard

x = 5
if x == 5:
    print("a")
      print("b")
# IndentationError: unexpected indent

Toutes les lignes d'un même bloc doivent avoir la même indentation. Deux espaces de trop suffisent à tout casser.

5) Comparer la saisie utilisateur sans la convertir

age = input("Ton age ? ")    # l'utilisateur tape 18 → age vaut "18"
if age == 18:
    print("Pile 18 ans")
else:
    print("Pas 18")

Affiche Pas 18, toujours, sans erreur : "18" == 18 vaut False. C'est le pire des trois mondes — pas de traceback, une sortie plausible, un programme faux. Correction : age = int(input("Ton age ? ")). Avec < ou > au lieu de ==, tu aurais au moins eu un TypeError pour te prévenir.

6) Des elif dans le mauvais ordre

score = 95
if score >= 50:
    print("Passable")       # ← 95 >= 50 est vrai : on s'arrête ICI
elif score >= 90:
    print("Excellent")      # jamais atteint pour aucun score !

Sortie : Passable. Aucune erreur : Python exécute le premier bloc vrai et ignore le reste. Avec des seuils, teste toujours du plus exigeant au moins exigeant (90 avant 70 avant 50). Vérifie ta chaîne avec une valeur par branche, plus les valeurs pile sur les seuils (90, 70, 50).

7. Lire les messages d'erreur

SyntaxError avec suggestion — le = de trop

  File "c:\Users\jtron\Claude\learnpython\note.py", line 2
    if age = 18:
       ^^^^^^^^
SyntaxError: invalid syntax. Maybe you meant '==' or ':=' instead of '='?
  1. Pas de Traceback (most recent call last) : c'est une erreur de syntaxe, le programme n'a exécuté aucune ligne (rappel de 01-1).
  2. Les ^^^ soulignent toute la condition ; la dernière ligne suggère la correction. (Le := proposé est un opérateur avancé, ignore-le pour l'instant.)

IndentationError — le bloc manquant

  File "c:\Users\jtron\Claude\learnpython\grade.py", line 3
    print("admis")
    ^^^^^
IndentationError: expected an indented block after 'if' statement on line 2

Le message donne DEUX numéros de ligne : la ligne 3 qui aurait dû être indentée, et la ligne 2 du if qui attend son bloc. IndentationError est une sous-espèce de SyntaxError : là aussi, rien n'a été exécuté.

TypeError — ordonner un texte et un nombre

Nombre ? Traceback (most recent call last):
  File "c:\Users\jtron\Claude\learnpython\check.py", line 3, in <module>
    if guess < secret:
       ^^^^^^^^^^^^^^
TypeError: '<' not supported between instances of 'str' and 'int'
  1. Dernière ligne : '<' not supported between instances of 'str' and 'int' — le message nomme l'opérateur ET les deux types coupables. Une str face à un int : c'est un input() non converti, à tous les coups.
  2. Remonte : ligne 3 de check.py, la comparaison est soulignée. Le if est la ligne du symptôme ; la cause est plus haut, à la création de guess (rappel de 01-2 : on corrige souvent au-dessus de la ligne du traceback).
  3. Note le Nombre ? avant le traceback : l'input() a fonctionné, le programme a planté juste après.

8. Exercices — faciles

Règles : nouveau fichier par exercice dans lessons/level-02-conditions-boucles/exercices/mes-reponses/, nommé ex-02-1-a.py, etc. Tape tout à la main. Prédis la sortie AVANT d'exécuter.

a) Demande un nombre entier à l'utilisateur et affiche positif, négatif ou nul. Trois branches, une seule s'exécute. Teste avec 7, -3 et 0.

b) Sans exécuter, écris sur papier la sortie de chaque ligne, puis vérifie :

print(3 == 3.0)
print("3" == 3)
print(10 != 10)
print("a" == "A")
print(5 >= 5)

c) Tarif de cinéma : demande l'âge et affiche le prix — gratuit avant 4 ans, 5.50 € de 4 à 17 ans, 9.20 € à partir de 18 ans. Contraintes : une chaîne if/elif/else (pas trois if séparés) ; teste les âges charnières 3, 4, 17, 18.

9. Exercices — moyens

a) Ce programme contient DEUX bugs — un bruyant, un silencieux. Trouve-les sans exécuter, dis quel message (ou quelle absence de message !) chacun produit, puis corrige :

age = input("Ton age ? ")
if age = 18:
    print("Pile la majorite !")
elif age > 18:
    print("Majeur")
else:
    print("Mineur")

b) Ce programme affiche Passable pour TOUTES les notes au-dessus de 50, même 95. Explique pourquoi (sans exécuter), puis répare en changeant seulement l'ordre des branches :

score = 95
if score >= 50:
    print("Passable")
elif score >= 70:
    print("Bien")
elif score >= 90:
    print("Excellent")
else:
    print("Echoue")

Vérifie ta version avec 95, 72, 50 et 30.

c) Demande un nombre entier et affiche s'il est pair positif, pair négatif, impair positif ou impair négatif (traite 0 comme pair positif). Contraintes : utilise % (vu en 01-2) pour la parité, et des conditions imbriquées (un if parité qui contient un if signe) — tu n'as pas encore and, c'est le but de l'exercice.

10. Exercices — difficiles

a) Demande trois nombres entiers et affiche le plus grand, SANS utiliser la fonction max() ni and/or (⏩ leçon 02-2). Puis améliore : si le plus grand apparaît plusieurs fois (ex. 7 7 2), affiche ex aequo : 7.

11. Mini-projet lié — le convertisseur passe au menu

Reprends le convertisseur de la fiche projects/mini-projects/02-convertisseur-unites.md : tu as maintenant TOUT ce qu'il faut pour le faire en entier (étapes 1 à 6). Le menu à trois choix (1 : °C → °F, 2 : km → miles, 3 : kg → livres) est une chaîne if/elif/elif/else ; le else attrape les choix invalides avec un message propre, sans traceback.

Piège central de la fiche, désormais dans tes cordes : le choix arrive comme chaîne ("1", pas 1) — compare avec choice == "1", ou convertis. Durée cible : 30–45 min.

12. Correction / méthode de correction

Les solutions détaillées sont dans solutions/serie-02-1-solutions.md.

Méthode : (1) finis TOUS les exercices avant d'ouvrir les solutions ; (2) compare le raisonnement, pas seulement le code — une solution différente qui marche est souvent valable ; (3) pour chaque écart, écris une ligne dans ton journal : « je pensais X, en fait Y » ; (4) refais de tête l'exercice raté, le lendemain.

13. À retenir

14. Questions de révision

  1. Quelle est la différence entre age = 18 et age == 18 ? Que se passe-t-il si on met le premier dans un if, et le second seul sur une ligne ?
  2. Dans une chaîne if/elif/elif, combien de blocs peuvent s'exécuter au maximum ? Et si deux conditions sont vraies ?
  3. Pourquoi "18" == 18 ne produit-il aucune erreur, et que vaut-il ? Pourquoi est-ce plus dangereux qu'un TypeError ?
  4. Qu'est-ce qui « ferme » un bloc en Python, puisqu'il n'y a ni accolade ni mot-clé de fin ?
  5. À quel if un else s'accroche-t-il quand il y a des conditions imbriquées ?
  6. Pourquoi faut-il tester score >= 90 AVANT score >= 50 dans un barème ?
  7. Cite deux erreurs de cette leçon détectées avant l'exécution (aucune ligne ne tourne) et une détectée pendant. Comment les distingues-tu au traceback ?
  8. Que vaut 2 < 3 <= 3 et comment Python le lit-il ?

15. Checklist de compréhension

Si une case reste vide : refais les exercices de la section correspondante demain, AVANT d'ouvrir la leçon suivante.

16. Commit conseillé

git add lessons/level-02-conditions-boucles/exercices/mes-reponses/
git commit -m "exercises: complete lesson 02-1 if elif else"

Puis, si c'est ta fin de session : entrée de journal + git push.