# Chapitre 02 — Les conditions : faire des choix > **⏱️ Durée estimée :** 4 heures > > **📋 Prérequis :** [Chapitre 01 — Variables, types et opérateurs](01-variables-types-operateurs.md) : variables, types `int`/`float`/`str`/`bool`, `input()` avec conversion, f-strings. > > **🎯 Objectifs — À la fin de ce chapitre, tu sauras :** > - comparer des valeurs avec `==`, `!=`, `<`, `>`, `<=`, `>=` et obtenir un booléen ; > - faire exécuter du code seulement si une condition est vraie, avec `if`, `elif` et `else` ; > - indenter correctement ton code pour délimiter des blocs ; > - combiner plusieurs conditions avec `and`, `or` et `not` ; > - utiliser l'expression conditionnelle sur une ligne (`a if condition else b`) ; > - choisir parmi plusieurs cas de façon élégante avec `match` / `case`. --- ## Cours ### 1. Pourquoi des conditions ? Jusqu'ici, tes programmes exécutaient toutes leurs lignes, de haut en bas, quoi qu'il arrive. Mais la vie est faite de choix : **s'il** pleut, je prends un parapluie, **sinon** je prends mes lunettes de soleil. Un distributeur de billets vérifie **si** ton code est correct. Un jeu vérifie **si** tu as perdu toutes tes vies. Les **conditions** permettent à un programme de prendre des décisions : exécuter certaines lignes seulement dans certaines situations. Pour cela, il faut d'abord savoir poser des questions dont la réponse est **oui** ou **non**, c'est-à-dire `True` ou `False`. ### 2. Les opérateurs de comparaison Un opérateur de comparaison compare deux valeurs et renvoie un **booléen** (`True` ou `False`). | Opérateur | Signification | Exemple | Résultat | |---|---|---|---| | `==` | est égal à | `5 == 5` | `True` | | `!=` | est différent de | `5 != 3` | `True` | | `<` | est strictement inférieur à | `3 < 5` | `True` | | `>` | est strictement supérieur à | `3 > 5` | `False` | | `<=` | est inférieur ou égal à | `5 <= 5` | `True` | | `>=` | est supérieur ou égal à | `4 >= 5` | `False` | ```python age = 17 print(age >= 18) print(age == 17) print(age != 17) majeur = age >= 18 # on peut stocker le résultat dans une variable print(majeur, type(majeur)) ``` Sortie : ```text False True False False ``` > ⚠️ **`=` n'est pas `==` !** Un seul `=` **affecte** une valeur (« colle l'étiquette »). Deux `==` **comparent** (« est-ce que c'est égal ? »). C'est l'erreur la plus fréquente de ce chapitre. #### 2.1. Comparer des chaînes On peut comparer des chaînes. L'égalité est **stricte** : majuscules, espaces et accents comptent. ```python print("chat" == "chat") print("chat" == "Chat") print("chat" == "chat ") print("été" == "ete") ``` Sortie : ```text True False False False ``` On peut aussi comparer des chaînes avec `<` et `>` : c'est l'ordre « alphabétique », mais attention, il suit en réalité les codes des caractères. Toutes les majuscules passent avant toutes les minuscules, et les chiffres sont comparés **caractère par caractère** : ```python print("abricot" < "banane") print("Zoo" < "abc") print("10" < "9") ``` Sortie : ```text True True True ``` `"10" < "9"` est vrai, car on compare d'abord `"1"` et `"9"`, et `"1"` vient avant. Encore une bonne raison de convertir les saisies en nombres avec `int()` ! #### 2.2. Comparer des nombres à virgule À cause de l'imprécision des floats vue au chapitre 01, l'égalité exacte entre floats est piégeuse : ```python print(0.1 + 0.2 == 0.3) print(abs((0.1 + 0.2) - 0.3) < 0.000001) ``` Sortie : ```text False True ``` Pour comparer deux floats, on vérifie plutôt que leur écart est minuscule. (Le module `math` propose `math.isclose()` pour ça, voir le [chapitre 09](09-modules-bibliotheque-standard.md).) #### 2.3. Comparaisons enchaînées Python permet d'écrire des encadrements comme en maths : ```python note = 14 print(10 <= note <= 20) # note est-elle entre 10 et 20 ? print(0 < note < 10) ``` Sortie : ```text True False ``` `10 <= note <= 20` signifie « `10 <= note` **et** `note <= 20` ». C'est très lisible, profites-en. ### 3. L'instruction `if` Voici la structure de base : ```python temperature = 31 if temperature > 30: print("Il fait très chaud !") print("Pense à boire de l'eau.") print("Bonne journée.") ``` Sortie : ```text Il fait très chaud ! Pense à boire de l'eau. Bonne journée. ``` Décortiquons : 1. Le mot-clé **`if`** (« si »), suivi d'une **condition** (`temperature > 30`), suivie de **deux-points** `:`. 2. En dessous, un **bloc** de lignes **indentées** (décalées vers la droite de 4 espaces). Ces lignes ne s'exécutent **que si** la condition vaut `True`. 3. La première ligne qui n'est plus indentée (`print("Bonne journée.")`) marque la fin du bloc : elle s'exécute dans tous les cas. Avec `temperature = 20`, la condition est fausse : le bloc est sauté. ```python temperature = 20 if temperature > 30: print("Il fait très chaud !") print("Pense à boire de l'eau.") print("Bonne journée.") ``` Sortie : ```text Bonne journée. ``` #### 3.1. L'indentation : la grammaire de Python Dans beaucoup de langages, on délimite les blocs avec des accolades `{ }`. Python, lui, utilise **l'indentation** : le décalage en début de ligne. Ce n'est pas une simple question d'esthétique : c'est **obligatoire**, et c'est ce qui dit à Python quelles lignes font partie du bloc. Pense à une recette : « Si tu as des invités : mets la table, sors les verres. » Les actions « mets la table » et « sors les verres » sont en retrait, car elles dépendent du « si ». Règles d'or : - la convention est d'indenter avec **4 espaces** (VS Code le fait automatiquement quand tu appuies sur Tab ou après les `:`) ; - toutes les lignes d'un même bloc ont **exactement** la même indentation ; - ne mélange jamais espaces et tabulations. Compare ces deux programmes, qui ne diffèrent que par l'indentation de la dernière ligne : ```python solde = 50 if solde < 0: print("Attention : compte à découvert !") print("Contacte ta banque.") ``` Ce premier programme n'affiche **rien** : la condition est fausse, donc les deux `print` sont sautés. ```python solde = 50 if solde < 0: print("Attention : compte à découvert !") print("Contacte ta banque.") ``` Sortie : ```text Contacte ta banque. ``` Dans le second programme, le dernier `print` ne fait plus partie du bloc : il s'exécute toujours. #### 3.2. Un bloc vide : `pass` Un bloc ne peut pas être vide. Si tu veux prévoir un `if` sans encore savoir quoi mettre dedans, écris `pass` (« ne rien faire ») : ```python niveau = 3 if niveau > 10: pass # TODO : gérer les niveaux bonus plus tard print("Partie lancée") ``` Sortie : ```text Partie lancée ``` ### 4. `else` : sinon… `else` (« sinon ») introduit le bloc à exécuter quand la condition est **fausse**. Exactement l'un des deux blocs est exécuté, jamais les deux, jamais aucun. ```python age = int(input("Quel âge as-tu ? ")) if age >= 18: print("Tu es majeur.") else: print("Tu es mineur.") print(f"Encore {18 - age} an(s) à attendre.") ``` Exemple d'exécution : ```text Quel âge as-tu ? 15 Tu es mineur. Encore 3 an(s) à attendre. ``` Le `else` est aligné avec le `if`, se termine par `:`, et n'a **pas** de condition. Un grand classique : tester si un nombre est pair, avec le modulo vu au chapitre 01. ```python nombre = int(input("Un nombre entier : ")) if nombre % 2 == 0: print(f"{nombre} est pair.") else: print(f"{nombre} est impair.") ``` Exemple d'exécution : ```text Un nombre entier : 7 7 est impair. ``` ### 5. `elif` : sinon, si… Quand il y a plus de deux possibilités, on enchaîne des `elif` (contraction de *else if*, « sinon, si »). ```python note = float(input("Ta note sur 20 : ")) if note >= 16: mention = "Très bien" elif note >= 14: mention = "Bien" elif note >= 12: mention = "Assez bien" elif note >= 10: mention = "Passable" else: mention = "Non admis" print(f"Mention : {mention}") ``` Exemple d'exécution : ```text Ta note sur 20 : 14.5 Mention : Bien ``` **Comment Python lit ce code :** il teste les conditions **dans l'ordre, de haut en bas**, et exécute **uniquement le premier bloc** dont la condition est vraie. Ensuite, il saute directement après toute la structure, sans regarder les autres. Avec `14.5` : `14.5 >= 16` est faux → on passe ; `14.5 >= 14` est vrai → mention « Bien », et c'est fini. Peu importe que `14.5 >= 12` soit aussi vrai : on ne le teste même pas. C'est pour cela que **l'ordre des conditions est crucial**. Regarde ce qui se passe si on les inverse : ```python note = 18 if note >= 10: mention = "Passable" elif note >= 16: mention = "Très bien" else: mention = "Non admis" print(mention) ``` Sortie : ```text Passable ``` Un 18 qui obtient « Passable » ! La première condition vraie gagne, et `18 >= 10` est vrai. Quand les conditions se chevauchent, va **du plus restrictif au moins restrictif**. **Résumé de la structure complète :** ```text if condition_1: ← obligatoire, toujours en premier ... elif condition_2: ← facultatif, autant qu'on veut ... elif condition_3: ... else: ← facultatif, toujours en dernier, sans condition ... ``` > 💡 **`if` successifs ou `elif` ?** Plusieurs `if` à la suite sont **indépendants** : chacun est testé. Une chaîne `if`/`elif` est **exclusive** : un seul bloc s'exécute. ```python nombre = 15 print("Avec des if séparés :") if nombre % 3 == 0: print(" divisible par 3") if nombre % 5 == 0: print(" divisible par 5") print("Avec elif :") if nombre % 3 == 0: print(" divisible par 3") elif nombre % 5 == 0: print(" divisible par 5") ``` Sortie : ```text Avec des if séparés : divisible par 3 divisible par 5 Avec elif : divisible par 3 ``` ### 6. Les conditions imbriquées Un bloc peut contenir lui-même un `if`. On parle de conditions **imbriquées**. Chaque niveau ajoute 4 espaces d'indentation. ```python a_un_billet = True age = 10 if a_un_billet: print("Bienvenue au parc !") if age < 12: print("Voici ton bracelet enfant.") else: print("Voici ton bracelet adulte.") else: print("Merci de passer par la billetterie.") ``` Sortie : ```text Bienvenue au parc ! Voici ton bracelet enfant. ``` Remarque `if a_un_billet:` : comme `a_un_billet` est déjà un booléen, inutile d'écrire `if a_un_billet == True:`. C'est plus court et plus naturel (« si on a un billet »). > 💡 Au-delà de deux ou trois niveaux d'imbrication, le code devient difficile à lire. Les opérateurs logiques de la section suivante permettent souvent d'« aplatir » les conditions. ### 7. Les opérateurs logiques `and`, `or`, `not` Ils permettent de combiner plusieurs conditions. #### 7.1. `and` : les deux doivent être vraies ```python age = 25 a_le_permis = True if age >= 18 and a_le_permis: print("Tu peux louer une voiture.") ``` Sortie : ```text Tu peux louer une voiture. ``` #### 7.2. `or` : au moins une doit être vraie ```python jour = "dimanche" if jour == "samedi" or jour == "dimanche": print("C'est le week-end !") ``` Sortie : ```text C'est le week-end ! ``` #### 7.3. `not` : inverse une condition ```python est_connecte = False if not est_connecte: print("Merci de te connecter.") ``` Sortie : ```text Merci de te connecter. ``` #### 7.4. Tables de vérité | `a` | `b` | `a and b` | `a or b` | `not a` | |---|---|---|---|---| | `True` | `True` | `True` | `True` | `False` | | `True` | `False` | `False` | `True` | `False` | | `False` | `True` | `False` | `True` | `True` | | `False` | `False` | `False` | `False` | `True` | Moyen mnémotechnique : `and` est **exigeant** (tout doit être vrai), `or` est **arrangeant** (une seule suffit). #### 7.5. Priorités et parenthèses L'ordre de priorité est : d'abord les comparaisons, puis `not`, puis `and`, puis `or`. Comme pour `*` et `+`, `and` passe avant `or`. Dans le doute, **mets des parenthèses** : ```python age = 15 accompagne = False est_vip = True # Entrée autorisée si : (majeur OU accompagné) ET VIP if (age >= 18 or accompagne) and est_vip: print("Entrée autorisée (version avec parenthèses)") else: print("Entrée refusée (version avec parenthèses)") # Sans parenthèses, Python lit : age >= 18 or (accompagne and est_vip) if age >= 18 or accompagne and est_vip: print("Entrée autorisée (version sans parenthèses)") else: print("Entrée refusée (version sans parenthèses)") ``` Sortie : ```text Entrée refusée (version avec parenthèses) Entrée refusée (version sans parenthèses) ``` Ici les deux résultats coïncident par hasard, mais changeons une valeur : ```python age = 20 accompagne = False est_vip = False if (age >= 18 or accompagne) and est_vip: print("Avec parenthèses : autorisé") else: print("Avec parenthèses : refusé") if age >= 18 or accompagne and est_vip: print("Sans parenthèses : autorisé") else: print("Sans parenthèses : refusé") ``` Sortie : ```text Avec parenthèses : refusé Sans parenthèses : autorisé ``` Les parenthèses changent le sens. Écris toujours ce que tu veux dire explicitement. #### 7.6. L'évaluation paresseuse Python est « paresseux » : avec `and`, si la première condition est fausse, il ne regarde même pas la seconde (le résultat sera faux de toute façon). Avec `or`, si la première est vraie, il s'arrête aussi. C'est utile pour se protéger d'une erreur : ```python nb_personnes = 0 total = 120 if nb_personnes != 0 and total / nb_personnes > 50: print("Repas cher !") else: print("Pas de calcul possible ou repas raisonnable.") ``` Sortie : ```text Pas de calcul possible ou repas raisonnable. ``` Comme `nb_personnes != 0` est faux, la division par zéro n'est jamais tentée. ### 8. La « vérité » des valeurs Une condition n'a pas forcément besoin d'être un booléen. Python sait évaluer n'importe quelle valeur comme vraie ou fausse, selon les règles de `bool()` vues au chapitre 01 : - **considérés comme faux** : `False`, `0`, `0.0`, la chaîne vide `""` (et `None`, ainsi que les collections vides, que tu verras plus tard) ; - **considéré comme vrai** : tout le reste. ```python pseudo = input("Ton pseudo (laisse vide pour rester anonyme) : ") if pseudo: print(f"Bienvenue, {pseudo} !") else: print("Bienvenue, visiteur anonyme !") ``` Exemple d'exécution (l'utilisateur appuie directement sur Entrée) : ```text Ton pseudo (laisse vide pour rester anonyme) : Bienvenue, visiteur anonyme ! ``` `if pseudo:` se lit « si le pseudo n'est pas vide ». C'est une écriture très courante en Python. ### 9. L'opérateur `in` avec les chaînes `in` teste si un morceau de texte est **contenu** dans une chaîne. C'est une façon très pratique d'éviter les longues séries de `or` : ```python email = "camille@exemple.fr" if "@" in email: print("L'adresse contient bien un @.") lettre = "e" if lettre in "aeiouy": print(f"'{lettre}' est une voyelle.") if "z" not in email: print("Pas de z dans l'adresse.") ``` Sortie : ```text L'adresse contient bien un @. 'e' est une voyelle. Pas de z dans l'adresse. ``` `in` fonctionne aussi avec les listes, les tuples et les dictionnaires, que tu découvriras au [chapitre 04](04-structures-de-donnees.md). ### 10. Rendre les saisies plus tolérantes Si tu demandes « oui ou non ? », l'utilisateur peut taper `oui`, `Oui`, `OUI` ou ` oui `… et `"Oui" == "oui"` est faux. Deux outils des chaînes (détaillés au [chapitre 06](06-chaines-et-comprehensions.md)) règlent le problème : - `texte.lower()` renvoie le texte en minuscules ; - `texte.strip()` renvoie le texte sans les espaces au début et à la fin. On peut les enchaîner : ```python reponse = input("Veux-tu continuer (oui/non) ? ").strip().lower() if reponse == "oui": print("C'est parti !") elif reponse == "non": print("À bientôt.") else: print("Je n'ai pas compris.") ``` Exemple d'exécution : ```text Veux-tu continuer (oui/non) ? OUI C'est parti ! ``` ### 11. L'expression conditionnelle (le « if sur une ligne ») Quand on veut simplement choisir entre **deux valeurs**, il existe une forme compacte : ```text valeur_si_vrai if condition else valeur_si_faux ``` ```python age = 16 statut = "majeur" if age >= 18 else "mineur" print(statut) nb_messages = 1 print(f"Tu as {nb_messages} message{'s' if nb_messages > 1 else ''}.") nb_messages = 3 print(f"Tu as {nb_messages} message{'s' if nb_messages > 1 else ''}.") ``` Sortie : ```text mineur Tu as 1 message. Tu as 3 messages. ``` C'est l'équivalent de : ```python age = 16 if age >= 18: statut = "majeur" else: statut = "mineur" print(statut) ``` Sortie : ```text mineur ``` > 💡 Réserve cette forme aux cas **simples**. Dès qu'il y a plus de deux possibilités ou plusieurs instructions, un `if`/`else` classique est plus lisible. ### 12. `match` / `case` : choisir parmi plusieurs cas Quand tu compares **une même valeur** à une série de possibilités, une longue chaîne de `elif` devient vite lourde : ```python commande = "aide" if commande == "jouer": print("Lancement du jeu...") elif commande == "aide": print("Voici l'aide.") elif commande == "quitter": print("Au revoir !") else: print("Commande inconnue.") ``` Sortie : ```text Voici l'aide. ``` Depuis Python 3.10, l'instruction **`match`** permet d'écrire cela plus clairement : ```python commande = "aide" match commande: case "jouer": print("Lancement du jeu...") case "aide": print("Voici l'aide.") case "quitter": print("Au revoir !") case _: print("Commande inconnue.") ``` Sortie : ```text Voici l'aide. ``` Comment ça marche : - `match valeur:` indique la valeur à examiner ; - chaque `case motif:` propose une possibilité. Python les teste **dans l'ordre** et exécute le **premier** qui correspond ; - `case _:` (le tiret bas) est le cas « joker » : il correspond à **tout**. C'est l'équivalent du `else`. Mets-le toujours en dernier. Pense à un aiguilleur de gare : le train (la valeur) arrive, et l'aiguilleur l'envoie sur la première voie (le `case`) qui lui correspond. #### 12.1. Plusieurs valeurs pour un même cas : `|` Le symbole `|` signifie « ou » dans un `case` : ```python jour = "samedi" match jour: case "samedi" | "dimanche": print("Week-end : grasse matinée !") case "lundi" | "mardi" | "mercredi" | "jeudi" | "vendredi": print("Semaine : debout !") case _: print("Ce n'est pas un jour valide.") ``` Sortie : ```text Week-end : grasse matinée ! ``` #### 12.2. Ajouter une condition : la garde `if` On peut capturer la valeur dans un nom, puis ajouter une condition avec `if` après le motif. On appelle ça une **garde** : ```python temperature = 23 match temperature: case 0: print("Pile le point de congélation.") case t if t < 0: print(f"{t} °C : il gèle !") case t if t < 25: print(f"{t} °C : température agréable.") case t: print(f"{t} °C : il fait chaud !") ``` Sortie : ```text 23 °C : température agréable. ``` Ici, `case t if t < 0:` signifie : « appelle la valeur `t`, et ce cas s'applique si `t < 0` ». Le dernier `case t:` sans garde attrape tout ce qui reste. > 💡 **`match` ou `if`/`elif` ?** Utilise `match` quand tu compares **une seule valeur** à des valeurs précises (commandes, choix de menu, codes). Pour des intervalles et des conditions complexes, `if`/`elif` reste souvent plus naturel. `match` est en réalité bien plus puissant (il sait décomposer des structures de données), tu en verras d'autres usages plus tard. ### 13. Exemple complet : la calculatrice Récapitulons avec une petite calculatrice qui utilise `match`, des conditions imbriquées et une vérification de la division par zéro. ```python # Calculatrice à 4 opérations a = float(input("Premier nombre : ")) operateur = input("Opérateur (+, -, *, /) : ").strip() b = float(input("Second nombre : ")) match operateur: case "+": print(f"{a} + {b} = {a + b}") case "-": print(f"{a} - {b} = {a - b}") case "*" | "x": print(f"{a} × {b} = {a * b}") case "/": if b == 0: print("Erreur : division par zéro impossible.") else: print(f"{a} / {b} = {a / b:.4g}") case _: print(f"Opérateur « {operateur} » inconnu.") ``` Exemple d'exécution : ```text Premier nombre : 10 Opérateur (+, -, *, /) : / Second nombre : 3 10.0 / 3.0 = 3.333 ``` Le format `:.4g` affiche au plus 4 chiffres significatifs, en supprimant les zéros inutiles. --- ## Pièges fréquents ### Piège 1 — Oublier les deux-points ```python age = 20 if age >= 18 print("Majeur") ``` ```text File "conditions.py", line 2 if age >= 18 ^ SyntaxError: expected ':' ``` **Correction :** chaque ligne `if`, `elif`, `else`, `match` et `case` se termine par `:`. ### Piège 2 — Oublier d'indenter ```python age = 20 if age >= 18: print("Majeur") ``` ```text File "conditions.py", line 3 print("Majeur") ^^^^^ IndentationError: expected an indented block after 'if' statement on line 2 ``` **Correction :** décale la ligne de 4 espaces : ` print("Majeur")`. ### Piège 3 — Une indentation incohérente ```python age = 20 if age >= 18: print("Majeur") print("fin") ``` ```text File "conditions.py", line 4 print("fin") ^ IndentationError: unindent does not match any outer indentation level ``` La dernière ligne a 2 espaces : elle n'est alignée ni avec le bloc (4 espaces) ni avec le `if` (0 espace). **Correction :** chaque ligne doit être alignée exactement sur un niveau existant. Dans VS Code, le nombre d'espaces de la ligne courante est indiqué en bas à droite, et le menu *Affichage* → *Afficher les espaces* (*Render Whitespace*) les rend visibles. ### Piège 4 — `=` au lieu de `==` ```python age = 20 if age = 18: print("Pile 18 ans") ``` ```text File "conditions.py", line 2 if age = 18: ^^^^^^^^ SyntaxError: invalid syntax. Maybe you meant '==' or ':=' instead of '='? ``` **Correction :** `if age == 18:`. Python te le suggère d'ailleurs dans le message. ### Piège 5 — Comparer une saisie non convertie ```python age = input("Âge : ") if age >= 18: print("Majeur") ``` ```text Âge : 20 Traceback (most recent call last): File "conditions.py", line 2, in if age >= 18: ^^^^^^^^^ TypeError: '>=' not supported between instances of 'str' and 'int' ``` Python refuse de comparer le texte `"20"` au nombre `18`. Et avec `==`, c'est encore plus sournois : `"18" == 18` ne provoque pas d'erreur, mais vaut toujours `False` ! **Correction :** `age = int(input("Âge : "))`. ### Piège 6 — Le faux ami `or` ```python couleur = "vert" if couleur == "rouge" or "bleu": print(f"{couleur} est une couleur primaire") ``` Sortie : ```text vert est une couleur primaire ``` Aucune erreur… mais un résultat faux ! Python lit `(couleur == "rouge") or ("bleu")`. Or `"bleu"` est une chaîne non vide, donc considérée comme **vraie** : la condition est toujours vraie. **Correction :** répète la comparaison, ou utilise `in` : ```python couleur = "vert" if couleur == "rouge" or couleur == "bleu" or couleur == "jaune": print(f"{couleur} est une couleur primaire") else: print(f"{couleur} n'est pas une couleur primaire") ``` Sortie : ```text vert n'est pas une couleur primaire ``` (Au chapitre 04, tu pourras écrire encore plus simplement `if couleur in ("rouge", "bleu", "jaune"):`.) ### Piège 7 — Un `else` orphelin ```python x = 3 if x > 0: print("positif") print("test terminé") else: print("négatif ou nul") ``` ```text File "conditions.py", line 5 else: ^^^^ SyntaxError: invalid syntax ``` Le `print` non indenté a « fermé » le `if` : le `else` n'a plus de `if` auquel se rattacher. Même erreur si un `elif` apparaît sans `if` avant lui. **Correction :** le `else` doit suivre **immédiatement** le bloc du `if` (ou du dernier `elif`), au même niveau d'indentation que le `if`. ### Piège 8 — Des conditions dans le mauvais ordre Comme vu à la section 5, avec `elif`, la **première** condition vraie gagne : ```python vitesse = 150 if vitesse > 90: print("Amende légère") elif vitesse > 130: print("Retrait de permis") ``` Sortie : ```text Amende légère ``` **Correction :** teste d'abord le cas le plus restrictif (`vitesse > 130`), puis `vitesse > 90`. --- ## Exercices ### Exercice 1 ⭐ — Positif, négatif ou nul Écris un programme qui demande un nombre (à virgule possible) et indique s'il est positif, négatif ou nul. Exemple d'exécution : ```text Un nombre : -4.5 -4.5 est négatif. ``` ### Exercice 2 ⭐ — Le plus grand de trois Écris un programme qui demande trois nombres entiers et affiche le plus grand, **sans utiliser** la fonction `max()`. Exemple d'exécution : ```text Premier nombre : 12 Deuxième nombre : 45 Troisième nombre : 7 Le plus grand est 45. ``` ### Exercice 3 ⭐ — Tarif du cinéma Un cinéma pratique les tarifs suivants : moins de 14 ans : 5 € ; de 14 à 25 ans inclus : 7.5 € ; de 26 à 64 ans : 11 € ; 65 ans et plus : 8 €. Écris un programme qui demande l'âge et affiche le tarif avec 2 décimales. Exemple d'exécution : ```text Âge : 25 Tarif : 7.50 € ``` ### Exercice 4 ⭐⭐ — Année bissextile Une année est **bissextile** si elle est divisible par 4 mais pas par 100, **ou** si elle est divisible par 400. Écris un programme qui demande une année et indique si elle est bissextile, en une seule condition combinant `and`, `or` et `%`. Exemples d'exécution : ```text Année : 2024 2024 est bissextile. ``` ```text Année : 1900 1900 n'est pas bissextile. ``` (2000 est bissextile, 2023 ne l'est pas.) ### Exercice 5 ⭐⭐ — Calcul de l'IMC L'indice de masse corporelle (IMC) se calcule ainsi : IMC = poids / taille², avec le poids en kg et la taille en mètres. Écris un programme qui demande le poids et la taille, affiche l'IMC avec une décimale, puis l'interprétation : | IMC | Interprétation | |---|---| | moins de 18.5 | insuffisance pondérale | | de 18.5 à moins de 25 | corpulence normale | | de 25 à moins de 30 | surpoids | | 30 et plus | obésité | Le programme doit refuser une taille négative ou nulle avec un message d'erreur. Exemple d'exécution : ```text Poids (kg) : 70 Taille (m) : 1.75 IMC : 22.9 (corpulence normale) ``` ### Exercice 6 ⭐⭐ — Le jour de la semaine Écris un programme qui demande un numéro de jour entre 1 et 7 et affiche le nom du jour correspondant (1 = lundi) ainsi que « (week-end) » pour le samedi et le dimanche. Utilise `match`/`case`. Un numéro invalide affiche un message d'erreur. Exemples d'exécution : ```text Numéro du jour (1-7) : 6 samedi (week-end) ``` ```text Numéro du jour (1-7) : 9 Numéro invalide : 9 ``` ### Exercice 7 ⭐⭐⭐ — Le type de triangle Écris un programme qui demande les longueurs des trois côtés d'un triangle (des entiers) et affiche : - `Ce n'est pas un triangle.` si une longueur est inférieure ou égale à 0, ou si un côté est plus grand ou égal à la somme des deux autres ; - sinon, `Triangle équilatéral.`, `Triangle isocèle.` ou `Triangle quelconque.` ; - et, en plus, ` Il est rectangle.` sur la même ligne si le triangle est rectangle (théorème de Pythagore : le carré du plus grand côté est égal à la somme des carrés des deux autres). Exemples d'exécution : ```text Côté a : 3 Côté b : 4 Côté c : 5 Triangle quelconque. Il est rectangle. ``` ```text Côté a : 2 Côté b : 2 Côté c : 9 Ce n'est pas un triangle. ``` ### Exercice 8 ⭐⭐⭐ — Le distributeur de boissons Un distributeur propose : `1` café (1.20 €), `2` thé (1.00 €), `3` chocolat (1.50 €). Écris un programme qui : 1. affiche le menu et demande le numéro de la boisson ; 2. si le choix est invalide, affiche « Choix invalide. » et s'arrête là ; 3. sinon, demande le montant inséré et : - si le montant est insuffisant, indique combien il manque ; - sinon, sert la boisson et indique la monnaie rendue (ou « Compte juste, merci ! » si elle vaut 0). Pour éviter les soucis d'imprécision des floats, fais tous les calculs **en centimes** (entiers) : `round(montant * 100)`. Exemple d'exécution : ```text 1. Café (1.20 €) 2. Thé (1.00 €) 3. Chocolat (1.50 €) Ton choix : 3 Montant inséré (€) : 2 Voici ton chocolat. Monnaie rendue : 0.50 € ``` --- ## Mini-projet ### Le quiz de culture générale **Objectif :** écrire un programme `quiz.py` qui pose 5 questions à l'utilisateur, compte les points et affiche une appréciation finale. **Cahier des charges :** 1. Le programme affiche un titre et demande le prénom du joueur. Si le prénom est vide, il utilise « Joueur mystère ». 2. Il pose **5 questions** de types variés : - au moins une question à réponse **texte**, tolérante aux majuscules et aux espaces (`strip().lower()`), et qui accepte plusieurs variantes de réponse (par exemple « paris » ou « la ville de paris ») ; - au moins une question à réponse **numérique** entière ; - au moins une question à réponse numérique où une réponse **approchée** rapporte la moitié des points (par exemple, à 5 ans près pour une date) ; - au moins une question **à choix multiples** (a, b, c, d) traitée avec `match`/`case`, qui affiche un message spécifique pour chaque mauvaise réponse ; - au moins une question **vrai/faux**. 3. Après chaque réponse, le programme affiche « Bonne réponse ! » ou la bonne réponse. 4. Le score (qui peut contenir des demi-points) est affiché à la fin sur 5, avec une appréciation selon le score : 5 → « Parfait ! », 4 ou plus → « Excellent », 2.5 ou plus → « Pas mal », moins → « Révise un peu ». 5. Le score est affiché sans décimale inutile : `4` plutôt que `4.0`, mais `3.5` reste `3.5` (indice : le format `:g`). **Exemple d'exécution :** ```text ===== QUIZ DE CULTURE GÉNÉRALE ===== Ton prénom : Léa Question 1 : Quelle est la capitale de la France ? > Paris Bonne réponse ! Question 2 : Combien de pattes a une araignée ? > 8 Bonne réponse ! Question 3 : En quelle année l'homme a-t-il marché sur la Lune ? > 1970 Presque ! C'était en 1969. (+0.5) Question 4 : Quel est le plus grand océan ? a) Atlantique b) Indien c) Pacifique d) Arctique > a Non, l'Atlantique est le deuxième. C'était le Pacifique. Question 5 : Vrai ou faux : la tomate est un fruit ? > vrai Bonne réponse ! Léa, ton score : 3.5 / 5 — Pas mal ``` **Étapes suggérées :** 1. Écris l'en-tête, la saisie du prénom (avec la valeur par défaut) et initialise `score = 0`. 2. Écris la question 1 et teste-la avec plusieurs variantes de réponse (`PARIS`, ` paris `, `Lyon`). 3. Ajoute les questions une par une, en testant à chaque fois les bonnes et les mauvaises réponses. 4. Termine par l'appréciation finale avec une chaîne `if`/`elif`/`else`. **Pistes d'amélioration :** - Ajoute un « mode difficile » choisi au début, qui change les questions posées. - Pour la question numérique, vérifie que la saisie contient bien des chiffres avec `reponse.isdigit()` avant de convertir, pour éviter le plantage (une approche plus robuste avec `try`/`except` sera vue au chapitre 08). - Au chapitre 03, tu pourras proposer de rejouer, ou donner plusieurs essais par question ; au chapitre 04, stocker les questions dans une liste. --- ## Corrigés
Corrigé de l'exercice 1 ```python # Positif, négatif ou nul nombre = float(input("Un nombre : ")) if nombre > 0: print(f"{nombre} est positif.") elif nombre < 0: print(f"{nombre} est négatif.") else: print(f"{nombre} est nul.") ``` Exemple d'exécution : ```text Un nombre : -4.5 -4.5 est négatif. ``` Le `else` n'a pas besoin de condition : si le nombre n'est ni positif ni négatif, il est forcément nul.
Corrigé de l'exercice 2 ```python # Le plus grand de trois nombres, sans max() a = int(input("Premier nombre : ")) b = int(input("Deuxième nombre : ")) c = int(input("Troisième nombre : ")) if a >= b and a >= c: plus_grand = a elif b >= c: # ici, on sait déjà que a n'est pas le plus grand plus_grand = b else: plus_grand = c print(f"Le plus grand est {plus_grand}.") ``` Exemple d'exécution : ```text Premier nombre : 12 Deuxième nombre : 45 Troisième nombre : 7 Le plus grand est 45. ``` Autre approche, très utile pour la suite : supposer que le premier est le plus grand, puis corriger si besoin. ```python a, b, c = 12, 45, 7 plus_grand = a if b > plus_grand: plus_grand = b if c > plus_grand: plus_grand = c print(f"Le plus grand est {plus_grand}.") ``` Sortie : ```text Le plus grand est 45. ``` Ici, on utilise des `if` **indépendants** (pas de `elif`) : chaque nombre doit être comparé. Cette technique se généralisera très bien avec les boucles au chapitre 03.
Corrigé de l'exercice 3 ```python # Tarif du cinéma selon l'âge age = int(input("Âge : ")) if age < 14: tarif = 5 elif age <= 25: tarif = 7.5 elif age < 65: tarif = 11 else: tarif = 8 print(f"Tarif : {tarif:.2f} €") ``` Exemple d'exécution : ```text Âge : 25 Tarif : 7.50 € ``` Grâce à `elif`, inutile d'écrire `14 <= age <= 25` : si on arrive au deuxième test, on sait déjà que `age >= 14`. Attention aux bornes : « de 14 à 25 ans inclus » se traduit par `<= 25`.
Corrigé de l'exercice 4 ```python # Année bissextile annee = int(input("Année : ")) if (annee % 4 == 0 and annee % 100 != 0) or annee % 400 == 0: print(f"{annee} est bissextile.") else: print(f"{annee} n'est pas bissextile.") ``` Exemples d'exécution : ```text Année : 2024 2024 est bissextile. ``` ```text Année : 1900 1900 n'est pas bissextile. ``` Les parenthèses ne sont pas strictement nécessaires ici (`and` est prioritaire sur `or`), mais elles rendent la règle bien plus lisible. Vérifie aussi : 2000 → divisible par 400 → bissextile ; 2023 → pas divisible par 4 → non.
Corrigé de l'exercice 5 ```python # Calcul de l'IMC poids = float(input("Poids (kg) : ")) taille = float(input("Taille (m) : ")) if taille <= 0: print("Erreur : la taille doit être strictement positive.") else: imc = poids / taille ** 2 if imc < 18.5: interpretation = "insuffisance pondérale" elif imc < 25: interpretation = "corpulence normale" elif imc < 30: interpretation = "surpoids" else: interpretation = "obésité" print(f"IMC : {imc:.1f} ({interpretation})") ``` Exemple d'exécution : ```text Poids (kg) : 70 Taille (m) : 1.75 IMC : 22.9 (corpulence normale) ``` On vérifie la taille **avant** de calculer, sinon une taille de 0 provoquerait une `ZeroDivisionError`. Tout le calcul est dans le bloc `else`, d'où le deuxième niveau d'indentation. `taille ** 2` est calculé avant la division, car `**` est prioritaire.
Corrigé de l'exercice 6 ```python # Nom du jour avec match/case numero = int(input("Numéro du jour (1-7) : ")) match numero: case 1: print("lundi") case 2: print("mardi") case 3: print("mercredi") case 4: print("jeudi") case 5: print("vendredi") case 6: print("samedi (week-end)") case 7: print("dimanche (week-end)") case _: print(f"Numéro invalide : {numero}") ``` Exemples d'exécution : ```text Numéro du jour (1-7) : 6 samedi (week-end) ``` ```text Numéro du jour (1-7) : 9 Numéro invalide : 9 ``` On convertit avec `int()`, car `case 6:` compare à l'**entier** 6 : la chaîne `"6"` ne correspondrait à aucun cas. Au chapitre 04, une liste des noms de jours permettra d'écrire ce programme en trois lignes.
Corrigé de l'exercice 7 ```python # Type de triangle a = int(input("Côté a : ")) b = int(input("Côté b : ")) c = int(input("Côté c : ")) if a <= 0 or b <= 0 or c <= 0 or a >= b + c or b >= a + c or c >= a + b: print("Ce n'est pas un triangle.") else: # Nature du triangle if a == b == c: message = "Triangle équilatéral." elif a == b or b == c or a == c: message = "Triangle isocèle." else: message = "Triangle quelconque." # Est-il rectangle ? On cherche le plus grand côté. if a >= b and a >= c: rectangle = a ** 2 == b ** 2 + c ** 2 elif b >= c: rectangle = b ** 2 == a ** 2 + c ** 2 else: rectangle = c ** 2 == a ** 2 + b ** 2 if rectangle: message = message + " Il est rectangle." print(message) ``` Exemples d'exécution : ```text Côté a : 3 Côté b : 4 Côté c : 5 Triangle quelconque. Il est rectangle. ``` ```text Côté a : 2 Côté b : 2 Côté c : 9 Ce n'est pas un triangle. ``` Points importants : - l'équilatéral est testé **avant** l'isocèle (un triangle équilatéral a aussi deux côtés égaux) ; - `a == b == c` est une comparaison enchaînée ; - `rectangle = a ** 2 == b ** 2 + c ** 2` stocke directement le **booléen** résultant de la comparaison, sans `if` ; - comme les côtés sont des entiers, la comparaison avec `==` est exacte (pas de souci de floats).
Corrigé de l'exercice 8 ```python # Distributeur de boissons (calculs en centimes) print("1. Café (1.20 €)") print("2. Thé (1.00 €)") print("3. Chocolat (1.50 €)") choix = input("Ton choix : ").strip() match choix: case "1": boisson, prix_centimes = "café", 120 case "2": boisson, prix_centimes = "thé", 100 case "3": boisson, prix_centimes = "chocolat", 150 case _: boisson, prix_centimes = "", 0 if boisson == "": print("Choix invalide.") else: montant = float(input("Montant inséré (€) : ")) montant_centimes = round(montant * 100) if montant_centimes < prix_centimes: manque = prix_centimes - montant_centimes print(f"Montant insuffisant : il manque {manque / 100:.2f} €.") else: rendu = montant_centimes - prix_centimes if rendu == 0: print(f"Voici ton {boisson}. Compte juste, merci !") else: print(f"Voici ton {boisson}. Monnaie rendue : {rendu / 100:.2f} €") ``` Exemple d'exécution : ```text 1. Café (1.20 €) 2. Thé (1.00 €) 3. Chocolat (1.50 €) Ton choix : 3 Montant inséré (€) : 2 Voici ton chocolat. Monnaie rendue : 0.50 € ``` Autre exécution : ```text 1. Café (1.20 €) 2. Thé (1.00 €) 3. Chocolat (1.50 €) Ton choix : 1 Montant inséré (€) : 1 Montant insuffisant : il manque 0.20 €. ``` On garde le choix sous forme de **texte** : ainsi, une saisie comme `abc` tombe simplement dans le `case _` au lieu de faire planter `int()`. Travailler en centimes évite les surprises : `1.5 - 1.2` donne `0.30000000000000004`, alors que `150 - 120` donne exactement `30`.
Corrigé du mini-projet ```python # quiz.py — Quiz de culture générale en 5 questions print("===== QUIZ DE CULTURE GÉNÉRALE =====") prenom = input("Ton prénom : ").strip() if not prenom: prenom = "Joueur mystère" score = 0 # --- Question 1 : réponse texte, plusieurs variantes acceptées --- print() print("Question 1 : Quelle est la capitale de la France ?") reponse = input("> ").strip().lower() if reponse == "paris" or reponse == "la ville de paris": print("Bonne réponse !") score += 1 else: print("Raté, c'était Paris.") # --- Question 2 : réponse numérique exacte --- print() print("Question 2 : Combien de pattes a une araignée ?") reponse = int(input("> ")) if reponse == 8: print("Bonne réponse !") score += 1 else: print("Raté, une araignée a 8 pattes.") # --- Question 3 : réponse numérique approchée --- print() print("Question 3 : En quelle année l'homme a-t-il marché sur la Lune ?") reponse = int(input("> ")) if reponse == 1969: print("Bonne réponse !") score += 1 elif abs(reponse - 1969) <= 5: print("Presque ! C'était en 1969. (+0.5)") score += 0.5 else: print("Raté, c'était en 1969.") # --- Question 4 : choix multiples avec match --- print() print("Question 4 : Quel est le plus grand océan ?") print(" a) Atlantique b) Indien c) Pacifique d) Arctique") reponse = input("> ").strip().lower() match reponse: case "c": print("Bonne réponse !") score += 1 case "a": print("Non, l'Atlantique est le deuxième. C'était le Pacifique.") case "b": print("Non, l'océan Indien est le troisième. C'était le Pacifique.") case "d": print("Non, l'Arctique est le plus petit ! C'était le Pacifique.") case _: print("Réponse invalide. C'était le Pacifique.") # --- Question 5 : vrai / faux --- print() print("Question 5 : Vrai ou faux : la tomate est un fruit ?") reponse = input("> ").strip().lower() if reponse == "vrai" or reponse == "v": print("Bonne réponse !") score += 1 else: print("Raté : botaniquement, la tomate est bien un fruit.") # --- Résultat final --- if score == 5: appreciation = "Parfait !" elif score >= 4: appreciation = "Excellent" elif score >= 2.5: appreciation = "Pas mal" else: appreciation = "Révise un peu" print() print(f"{prenom}, ton score : {score:g} / 5 — {appreciation}") ``` Exemple d'exécution (mêmes réponses que dans l'énoncé) : ```text ===== QUIZ DE CULTURE GÉNÉRALE ===== Ton prénom : Léa Question 1 : Quelle est la capitale de la France ? > Paris Bonne réponse ! Question 2 : Combien de pattes a une araignée ? > 8 Bonne réponse ! Question 3 : En quelle année l'homme a-t-il marché sur la Lune ? > 1970 Presque ! C'était en 1969. (+0.5) Question 4 : Quel est le plus grand océan ? a) Atlantique b) Indien c) Pacifique d) Arctique > a Non, l'Atlantique est le deuxième. C'était le Pacifique. Question 5 : Vrai ou faux : la tomate est un fruit ? > vrai Bonne réponse ! Léa, ton score : 3.5 / 5 — Pas mal ``` Remarques : - `if not prenom:` détecte une chaîne vide (section 8 du cours). - `abs(reponse - 1969) <= 5` signifie « à 5 ans près » : `abs()` donne l'écart sans se soucier du signe (1964 et 1974 sont acceptés). - Le `elif` de la question 3 n'est testé que si la réponse n'est pas exacte : une réponse exacte ne rapporte donc pas 1.5 point. - `{score:g}` affiche `4` pour `4` ou `4.0`, et `3.5` pour `3.5`. - On remarque beaucoup de répétitions d'une question à l'autre : les boucles (chapitre 03), les listes (chapitre 04) et les fonctions (chapitre 05) permettront de les éliminer.
--- ## Récapitulatif **Points clés :** - Les opérateurs de comparaison `==`, `!=`, `<`, `>`, `<=`, `>=` renvoient un booléen. Ne confonds pas `=` (affectation) et `==` (comparaison). - Structure : `if condition:` puis un bloc **indenté de 4 espaces**. `elif` et `else` sont facultatifs ; `else` n'a jamais de condition. - Dans une chaîne `if`/`elif`/`else`, **seul le premier bloc dont la condition est vraie** s'exécute : l'ordre des conditions compte. - `and` (toutes vraies), `or` (au moins une vraie), `not` (inverse). Priorité : `not` > `and` > `or` ; mets des parenthèses pour être clair. - `a <= x <= b` permet d'écrire un encadrement. - `0`, `0.0`, `""` sont considérés comme faux ; `if texte:` signifie « si le texte n'est pas vide ». - `in` teste si un morceau de texte est contenu dans une chaîne. - `valeur1 if condition else valeur2` choisit entre deux valeurs sur une ligne. - `match valeur:` / `case ...:` / `case _:` compare une valeur à plusieurs cas ; `|` regroupe plusieurs valeurs, `case x if ...:` ajoute une garde. - Convertis toujours les saisies numériques avant de les comparer, et normalise les saisies texte avec `.strip().lower()`. **Checklist de validation :** - [ ] Je sais écrire une condition avec `if`, `elif` et `else`, avec les `:` et l'indentation correcte. - [ ] Je sais prédire quel bloc s'exécute dans une chaîne de `elif`, et j'ordonne mes conditions en conséquence. - [ ] Je sais combiner des conditions avec `and`, `or`, `not` et je connais le piège `x == "a" or "b"`. - [ ] Je sais utiliser une comparaison enchaînée et l'expression `a if condition else b`. - [ ] Je sais écrire un `match`/`case` avec un cas par défaut `_`. - [ ] Mes programmes ne plantent plus sur une division par zéro grâce à une vérification préalable. - [ ] J'ai réalisé le quiz et testé chaque question avec une bonne et une mauvaise réponse. --- [← Chapitre précédent](01-variables-types-operateurs.md) | [Sommaire](README.md) | [Chapitre suivant →](03-boucles.md)