đ Expressions boolĂ©ennes
- Expressions booléennes
- if
- elif
- else
- Comparaison
- Imbrication
- DRY
- Forme compacte
- Validation raise/try/except
- Trace
- Activités
- *match/case*
Une expression booléenne est une expression qui évalue à une valeur de vérité (bool), c'est-à -dire soit True (vrai) soit False (faux).
Elles sont utilisées pour prendre des décisions dans le code, comme dans les instructions conditionnelles (if, elif, else) et les boucles (while, for).
Les opérateurs de comparaison sont utilisés pour comparer deux valeurs.
Voici les principaux opérateurs de comparaison en Python :
| Opérateur | Description | Exemple | Résultat |
|---|---|---|---|
| == | Ăgal Ă | a == b | True si Ă©gaux |
| != | Différent de | a != b | True si différents |
| < | Inférieur à | a < b | True si a plus petit |
| <= | Inférieur ou égal à | a <= b | True si a plus petit ou égal |
| > | Supérieur à | a > b | True si a plus grand |
| >= | Supérieur ou égal à | a >= b | True si a plus grand ou égal |
| and | ET logique | a and b | True si les deux sont True |
| or | OU logique | a or b | True si au moins un est True |
| not | NON logique | not a | Inverse la valeur booléenne |
a = 5
b = 10
print(a < b) # Affiche True
print(a == b) # Affiche False
print(a + 5 >= b - max(1, min(4, a, 6), 5)) # Affiche True, explications ci-dessous!
Les 2 opĂ©randes dâun opĂ©rateur de comparaison peuvent ĂȘtre le rĂ©sultat de l'Ă©valuation dâexpressions.
Python Ă©value lâexpression selon la prioritĂ© des opĂ©rateurs, en remplaçant chaque sous-expression par sa valeur rĂ©sultante.
Voici comment Python Ă©value lâinstruction #5, Ă©tape par Ă©tape :
print(a + 5 >= b - max(1, min(4, a, 6), 5)) # Instruction originale
print(5 + 5 >= b - max(1, min(4, 5, 6), 5)) # Remplace 'a' par sa valeur
print(10 >= b - max(1, min(4, 5, 6), 5)) # Calcule la somme de '5 + 5'
print(10 >= 10 - max(1, min(4, 5, 6), 5)) # Remplace 'b' par sa valeur
print(10 >= 10 - max(1, 4, 5)) # La fonction min(...) doit ĂȘtre rĂ©solue avant la fonction max(...)
print(10 >= 10 - 5) # La fonction max(...) est résolue
print(10 >= 5) # L'opération >=
print(True) # Affiche "True" dans la console
Les opérateurs logiques sont utilisés pour combiner plusieurs expressions booléennes.
Ils sont inclus dans le tableau des expressions booléennes ci-dessus (and, or, not).
La priorité des opérateurs détermine l'ordre dans lequel les opérations sont effectuées dans une expression.
En Python, la priorité des opérateurs est la suivante (de la plus haute à la plus basse) :
- ParenthĂšses
() - Opérateurs de comparaison (
==,!=,<,<=,>,>=) - Opérateur
not - Opérateur
and - Opérateur
or
Un ordre plus exhaustif des priorités des opérateurs est disponible ici dans l'aide-mémoire.
a = 5
b = 10
c = 15
print(a < b and b < c) # ĂvaluĂ© comme (a < b) and (b < c), affiche True
print(a < b or b > c) # ĂvaluĂ© comme (a < b) or (b > c), affiche True
print(not a < b) # ĂvaluĂ© comme not (a < b), affiche False
# On peut utiliser des parenthÚses pour modifier l'ordre d'évaluation :
print(a < b or b > c and a == 5) # ĂvaluĂ© comme a < b or (b > c and a == 5), affiche True
print((a < b or b > c) and a == 5) # ĂvaluĂ© comme (a < b or b > c) and a == 5, affiche True
On peut stocker le résultat d'une expression booléenne dans une variable pour une utilisation ultérieure.
a = 5
b = 10
est_plus_petit = a < b # est_plus_petit sera True
est_egal = a == b # est_egal sera False
print(est_plus_petit) # Affiche True
print(est_egal) # Affiche False
Les explications de cette section étaient-elles claires ?
C'est bien beau, ça, les expressions booléennes, mais à quoi ça sert?
đ Elles servent principalement Ă contrĂŽler le flux d'exĂ©cution du programme,
c'est-Ă -dire Ă dĂ©cider quelles parties du code doivent ĂȘtre exĂ©cutĂ©es en fonction de certaines conditions.
Voici un exemple simple d'instruction conditionnelle en Python :
age = 18
if age >= 18 :
print("Vous ĂȘtes majeur.")
Dans cet exemple, l'instruction if vérifie si la variable age est supérieure ou égale à 18.
Si c'est le cas (si la condition est True), le code indentĂ© sous l'instruction if est exĂ©cutĂ©, affichant "Vous ĂȘtes majeur.".
Si la condition est False, le code indenté n'est pas exécuté.
En Python, l'indentation (les espaces ou tabulations avant une ligne de code) est cruciale pour définir les blocs de code.
Le code qui doit ĂȘtre exĂ©cutĂ© conditionnellement doit ĂȘtre indentĂ© sous l'instruction if.
Par exemple :
if condition :
# Code indenté, exécuté si la condition est True
faire_quelque_chose_conditionnel()
faire_autre_chose_conditionnel()
# Code non indenté, exécuté indépendamment de la condition
faire_autre_chose_en_tout_temps()
Exemple d'erreur courante due Ă une mauvaise indentation :
if condition :
faire_quelque_chose() # Erreur : cette ligne doit ĂȘtre indentĂ©e
Exemple concret :
age = 20
if age >= 18 :
print("Vous ĂȘtes majeur.")
print("Vous avez le droit de vote!")
print("Un grand pouvoir implique de grandes responsabilités.")
print("Bienvenue!") # Toujours exécuté, indépendamment de l'ùge
Les explications de cette section étaient-elles claires ?
Non!
elif est la contraction de "else if", qui signifie "sinon si".
Elle permet de vérifier une autre condition si la premiÚre condition dans l'instruction if est False.
Par exemple :
age = 16
if age >= 18 :
print("Vous ĂȘtes majeur.")
elif age >= 13 :
print("Vous ĂȘtes adolescent.")
On peut avoir plusieurs clauses elif pour vérifier plusieurs conditions différentes.
Par exemple :
age = 10
if age >= 18 :
print("Vous ĂȘtes majeur.")
elif age >= 13 :
print("Vous ĂȘtes adolescent.")
elif age >= 3 :
print("Vous ĂȘtes un enfant.")
L'ordre des conditions est important.
Les conditions sont évaluées de haut en bas, et la premiÚre condition qui est True déclenche l'exécution du bloc de code correspondant.
Par exemple, dans le code suivant, la condition age >= 13 sera toujours True pour tous les adultes, et la condition age >= 18 ne sera jamais atteinte :
age = 21
if age >= 13 :
print("Vous ĂȘtes adolescent.")
elif age >= 18 :
print("Vous ĂȘtes majeur.")
Pour éviter cela, il faut toujours commencer par la condition la plus restrictive (la plus élevée) et descendre vers les conditions moins restrictives :
age = 21
if age >= 18 :
print("Vous ĂȘtes majeur.")
elif age >= 13 :
print("Vous ĂȘtes adolescent.")
elif sans ifUne clause elif doit toujours ĂȘtre prĂ©cĂ©dĂ©e d'une instruction if.
Par exemple, le code suivant est incorrect et provoquera une erreur de syntaxe :
age = 16
elif age >= 13 : # Erreur : 'elif' sans 'if'
print("Vous ĂȘtes adolescent.")
Les explications de cette section étaient-elles claires ?
else signifie "sinon".
Elle permet de définir un bloc de code qui sera exécuté si toutes les conditions précédentes (if et elif) sont False.
Par exemple :
age = 10
if age >= 18 :
print("Vous ĂȘtes majeur.")
elif age >= 13 :
print("Vous ĂȘtes adolescent.")
else :
print("Vous ĂȘtes un enfant.")
Dans cet exemple, si age est infĂ©rieur Ă 13, le message "Vous ĂȘtes un enfant." sera affichĂ©.
La clause else est souvent utilisée à la fin d'une série d'instructions if et elif pour capturer tous les cas non couverts par les conditions précédentes.
Par exemple :
score = 85
if score >= 90 :
print("Excellent")
elif score >= 75 :
print("Bien")
elif score >= 50 :
print("Passable")
else :
print("Ăchec")
Contrairement Ă if et elif, la clause else ne prend pas de condition.
Elle est simplement exécutée si toutes les conditions précédentes sont False. Par exemple, le code suivant est incorrect et provoquera une erreur de syntaxe :
score = 85
if score >= 90 :
print("Excellent")
elif score >= 75 :
print("Bien")
elif score >= 50 :
print("Passable")
else score < 50 : # Erreur : 'else' ne doit pas avoir de condition
print("Ăchec")
Il est possible d'utiliser else directement aprĂšs un if, sans avoir besoin de elif.
Par exemple :
age = 20
if age >= 18 :
print("Vous ĂȘtes majeur.")
else :
print("Vous ĂȘtes mineur.")
Les structures conditionnelles (if/elif/else, match/case) peuvent ĂȘtre utilisĂ©es Ă l'intĂ©rieur de fonctions.
Exemple 1 â if/else simple :
def est_pair(n):
if n % 2 == 0:
return True # Faire modulo 2 sur un nombre pair donne toujours 0!
else:
return False
a = 33
b = 52
print(f"{a} est un nombre pair : {est_pair(a)}")
print(f"{b} est un nombre pair : {est_pair(b)}")
33 est un nombre pair : False
52 est un nombre pair : True
Exemple 2 â if/else avec paramĂštre optionnel et calcul par palier :
La fonction suivante calcule la paie brute d'un employé. Elle accepte un troisiÚme paramÚtre optionnel pour activer le calcul des heures supplémentaires au taux double.
def calculer_paie_brute(nb_heures, taux_horaire, temps_double_apres_40_heures=False):
salaire = nb_heures * taux_horaire
if temps_double_apres_40_heures and nb_heures >= 40:
nb_heures_temps_supp = nb_heures - 40
salaire = salaire + nb_heures_temps_supp * taux_horaire * 2
return salaire
nb_heures = 45
taux_horaire = 20
print(f"Calcul de la paie brute pour {nb_heures} heures Ă un taux horaire de {taux_horaire}$/h.")
print(f" Avec le temps > 40 payé au taux doublé : {calculer_paie_brute(nb_heures, taux_horaire, True)}$")
print(f" Avec le temps > 40 payé au taux régulier : {calculer_paie_brute(nb_heures, taux_horaire)}$")
Calcul de la paie brute pour 45 heures Ă un taux horaire de 20$/h.
Avec le temps > 40 payé au taux doublé : 1100$
Avec le temps > 40 payé au taux régulier : 900$
Exemple 3 â if/elif/else avec trois listes parallĂšles :
On peut stocker plusieurs valeurs dans des listes parallĂšles et appeler notre fonction sur chaque Ă©lĂ©ment. Voici une liste d'Ă©lĂ©ments du tableau pĂ©riodique avec leur masse atomique (en u.m.a.) et leur nombre de protons. On veut classifier la stabilitĂ© de chaque noyau en fonction du rapport entre sa masse atomique et son nombre de protons â un indicateur simplifiĂ© du ratio neutrons/protons :
def stabilite_noyau(masse_atomique, nb_protons):
"""
Classifie la stabilité d'un noyau selon le ratio neutrons/protons.
ParamĂštres :
masse_atomique (int) : Nombre de masse de l'élément (protons + neutrons).
nb_protons (int) : Nombre de protons dans le noyau.
Retourne :
str : "stable", "légÚrement instable" ou "trÚs instable".
"""
nb_neutrons = masse_atomique - nb_protons
ratio = nb_neutrons / nb_protons
if ratio <= 1.1 :
return "stable"
elif ratio <= 1.5 :
return "légÚrement instable"
else :
return "trĂšs instable"
masses_atomiques = [1,4,7,12,14,16]
symboles = ["H","He","Li","C","N","O"]
nb_protons = [1,2,3,6,7,8]
print(f"{symboles[0]} (masse {masses_atomiques[0]}) - stabilité : {stabilite_noyau(masses_atomiques[0], nb_protons[0])}")
print(f"{symboles[1]} (masse {masses_atomiques[1]}) - stabilité : {stabilite_noyau(masses_atomiques[1], nb_protons[1])}")
print(f"{symboles[2]} (masse {masses_atomiques[2]}) - stabilité : {stabilite_noyau(masses_atomiques[2], nb_protons[2])}")
print(f"{symboles[3]} (masse {masses_atomiques[3]}) - stabilité : {stabilite_noyau(masses_atomiques[3], nb_protons[3])}")
print(f"{symboles[4]} (masse {masses_atomiques[4]}) - stabilité : {stabilite_noyau(masses_atomiques[4], nb_protons[4])}")
print(f"{symboles[5]} (masse {masses_atomiques[5]}) - stabilité : {stabilite_noyau(masses_atomiques[5], nb_protons[5])}")
H (masse 1) - stabilité : stable
He (masse 4) - stabilité : stable
Li (masse 7) - stabilité : légÚrement instable
C (masse 12) - stabilité : stable
N (masse 14) - stabilité : stable
O (masse 16) - stabilité : stable
đ On remarque qu'on rĂ©pĂšte 6 fois la mĂȘme instruction print en changeant seulement l'index.
C'est exactement le genre de répétition qu'une boucle for éliminera en quelques lignes, vous verrez ça bientÎt!
Les explications de cette section étaient-elles claires ?
if if if vs if elif else â ce n'est pas la mĂȘme chose!C'est l'une des erreurs les plus frĂ©quentes chez les dĂ©butants :
utiliser plusieurs if indĂ©pendants lĂ oĂč un if/elif/else serait nĂ©cessaire.
La différence est fondamentale et peut avoir des impacts sur les performances.
Prenons cet exemple avec score = 95 :
# Version avec des if if if
score = 95
if score >= 90 :
print("Excellent") # â
Exécuté (95 >= 90 est True)
if score >= 75 :
print("Bien") # â
Exécuté (95 >= 75 est True)
if score >= 50 :
print("Passable") # â
Exécuté (95 >= 50 est True)
else :
print("Ăchec") # âïž Bloc ignorĂ© (car la condition score >= 50 a donnĂ© True)
Résultat affiché :
Excellent
Bien
Passable
đ Avec des if indĂ©pendants, Python Ă©value chaque condition sĂ©par Ă©ment, de haut en bas, sans jamais s'arrĂȘter. Comme les 3 conditions sont True pour score = 95, les 3 blocs sont exĂ©cutĂ©s. Ce n'est presque certainement pas ce qu'on voulait! Il aurait Ă©tĂ© prĂ©fĂ©rable que Python arrĂȘte dâĂ©valuer les autres conditions dĂšs quâil trouve une condition donnant True.
if elif else# Version avec if elif else
score = 95
if score >= 90 :
print("Excellent") # â
ExĂ©cutĂ© (95 >= 90 est True) â Python arrĂȘte ici
elif score >= 75 :
print("Bien") # âïž Bloc ignorĂ© (car une condition d'un bloc prĂ©cĂ©dent a donnĂ© True)
elif score >= 50 :
print("Passable") # âïž Bloc ignorĂ© (car une condition d'un bloc prĂ©cĂ©dent a donnĂ© True)
else :
print("Ăchec") # âïž Bloc ignorĂ© (car une condition d'un bloc prĂ©cĂ©dent a donnĂ© True)
Résultat affiché :
Excellent
đ Avec if/elif/else, dĂšs qu'une condition est True, Python exĂ©cute le bloc correspondant et saute immĂ©diatement le reste : les autres conditions ne sont jamais Ă©valuĂ©es. Un seul bloc s'exĂ©cute, peu importe le nombre de elif. Python a donc exĂ©cutĂ© uniquement le bloc associĂ© Ă score >= 90.
| Situation | Utiliser |
|---|---|
| Les cas sont mutuellement exclusifs (un seul doit s'exécuter) | if / elif / else |
| Les vérifications sont indépendantes les unes des autres | Plusieurs if séparés |
Exemple oĂč plusieurs if sĂ©parĂ©s sont appropriĂ©s :
ph = 3.5
temperature_celsius = 85
pression_atm = 1.8
if ph < 6 :
print("â ïž Solution acide : portez des gants de protection.") # â
Exécuté
if temperature_celsius > 60 :
print("đĄïž TempĂ©rature Ă©levĂ©e : risque de brĂ»lure.") # â
Exécuté
if pression_atm > 1.5 :
print("đš Pression Ă©levĂ©e : vĂ©rifiez l'Ă©tanchĂ©itĂ© du systĂšme.") # â
Exécuté
Ici, les 3 avertissements sont complémentaires et ont du sens ensemble. Plusieurs if indépendants sont donc le bon choix.
Pour récapituler, la structure d'une instruction conditionnelle en Python est la suivante :
if: Obligatoire pour commencer une instruction conditionnelle.elif: Les blocselifsont optionnels.- Il peut y en avoir 0, 1, 2 ou plus.
- Chaque
elifvérifie une condition, seulement si toutes les conditions précédentes sontFalse.
else: Le blocelseest optionnel.- Il ne peut y avoir quâun seul
else. - Il est exécuté si toutes les conditions précédentes sont
False. - Le bloc
elsene prend pas de condition.
- Il ne peut y avoir quâun seul
- Indentation : le code Ă exĂ©cuter conditionnellement doit ĂȘtre indentĂ© sous l'instruction correspondante.
- Ordre des conditions :
- les conditions sont évaluées de haut en bas;
- la premiĂšre condition
Truedéclenche l'exécution du bloc de code correspondant; - dans une structure
if/elif/else, les autres conditions sont ignorĂ©es dĂšs quâune condition estTrue.
Les explications de cette section étaient-elles claires ?
Il est tout à fait possible d'écrire une structure conditionnelle à l'intérieur d'une autre.
On appelle cela des structures imbriquées (nested en anglais).
C'est utile quand une décision dépend d'une autre, comme dans la vraie vie!
Imaginons qu'on veuille classer un échantillon selon son pH ET sa température :
ph = 4.2
temperature_celsius = 75
if ph < 7 :
print("Solution acide.")
if temperature_celsius > 60 : # Condition imbriquée dans le if
print("â ïž Acide ET chaude : danger!")
else :
print("Acide mais à température normale.")
else :
print("Solution neutre ou basique.")
if temperature_celsius > 60 : # Condition imbriquée dans le else
print("â ïž Solution chaude : manipuler avec prĂ©caution.")
else :
print("Conditions stables.")
Résultat affiché avec ph = 4.2 et temperature_celsius = 75 :
Solution acide.
â ïž Acide ET chaude : danger!
đ Python entre d'abord dans le bloc if ph < 7, puis Ă©value la condition sur la tempĂ©rature seulement Ă l'intĂ©rieur de ce bloc.
Chaque niveau d'imbrication ajoute un niveau d'indentation supplémentaire.
C'est ce qui permet Ă Python de savoir Ă quel bloc appartient chaque instruction.
if condition_1 :
# Bloc de la condition 1 (indenté 1 fois)
if condition_2 :
# Bloc de la condition 2 (indenté 2 fois)
faire_quelque_chose()
else :
# Bloc else de la condition 2 (indenté 2 fois)
faire_autre_chose()
else :
# Bloc else de la condition 1 (indenté 1 fois)
faire_encore_autre_chose()
En astronomie, on peut classer une étoile selon sa luminosité et sa température de surface :
luminosite = 500 # En unités solaires
temperature_K = 8000 # En kelvins
if luminosite >= 100 :
print("Ătoile trĂšs lumineuse.")
if temperature_K >= 10000 :
print("â Classification : Ă©toile bleue gĂ©ante.")
elif temperature_K >= 6000 :
print("â Classification : Ă©toile blanche gĂ©ante.")
else :
print("â Classification : supergĂ©ante froide.")
elif luminosite >= 1 :
print("Ătoile de luminositĂ© moyenne.")
if temperature_K >= 6000 :
print("â Classification : Ă©toile de la sĂ©quence principale (type solaire ou plus chaud).")
else :
print("â Classification : Ă©toile naine froide.")
else :
print("Ătoile peu lumineuse.")
if temperature_K >= 4000 :
print("â Classification : naine blanche.")
else :
print("â Classification : naine brune.")
Résultat affiché avec luminosite = 500 et temperature_K = 8000 :
Ătoile trĂšs lumineuse.
â Classification : Ă©toile blanche gĂ©ante.
đ Le premier if/elif/else traite la luminositĂ©, puis, Ă l'intĂ©rieur de chacun de ses blocs, un second if/elif/else affine la classification selon la tempĂ©rature.
Plus on imbrique de niveaux, plus le code devient difficile à lire et à déboguer.
En général, une bonne rÚgle de base est de ne pas dépasser 2 à 3 niveaux.
Si vous vous retrouvez avec plus de 3 niveaux, c'est souvent le signe que le code pourrait ĂȘtre rĂ©organisĂ©, par exemple en utilisant des fonctions.
# â Difficile Ă lire â trop de niveaux d'imbrication
if condition_1 :
if condition_2 :
if condition_3 :
if condition_4 :
faire_quelque_chose() # On s'y perd!
# â
Plus lisible â on peut souvent combiner les conditions avec and
if condition_1 and condition_2 and condition_3 and condition_4 :
faire_quelque_chose()
| Situation | Approche recommandée |
|---|---|
| La 2e condition ne s'évalue que si la 1re est vraie | Imbrication |
| Les conditions sont indépendantes les unes des autres | Plusieurs if séparés |
| Les conditions peuvent ĂȘtre combinĂ©es simplement | and / or dans un seul if |
đ L'imbrication est le bon choix quand la logique est hiĂ©rarchique : on vĂ©rifie d'abord une catĂ©gorie gĂ©nĂ©rale, puis on affine Ă l'intĂ©rieur de cette catĂ©gorie.
Les explications de cette section étaient-elles claires ?
En programmation, on suit souvent le principe DRY (Don't Repeat Yourself).
Si vous remarquez que vous Ă©crivez la mĂȘme instruction plusieurs fois dans des blocs diffĂ©rents, c'est le signe qu'elle n'est pas vraiment conditionnelle!
Si une instruction se retrouve à la fois dans le if et dans le else, elle s'exécuterait dans tous les cas de toute façon.
Elle devrait donc ĂȘtre placĂ©e en dehors du bloc conditionnel â soit avant, soit aprĂšs, selon sa position dans les blocs de code.
Repérez l'instruction répétée inutilement dans les deux blocs :
# Version redondante
temperature = 37.8
if temperature > 37.5 :
print("Initialisation du protocole de mesure...") # â RĂ©pĂ©tĂ© au dĂ©but des 2 blocs!
print("â ïž FiĂšvre dĂ©tectĂ©e : consulter un mĂ©decin.")
else :
print("Initialisation du protocole de mesure...") # â RĂ©pĂ©tĂ© au dĂ©but des 2 blocs!
print("â
Température normale.")
Peu importe la valeur de temperature, l'initialisation du protocole est toujours affichée.
La répéter dans les deux blocs est inutile et rend le code plus difficile à maintenir.
# Version sans redondance
temperature = 37.8
print("Initialisation du protocole de mesure...") # â
Exécuté dans tous les cas avant les 2 blocs
if temperature > 37.5 :
print("â ïž FiĂšvre dĂ©tectĂ©e : consulter un mĂ©decin.")
else :
print("â
Température normale.")
Le code est plus court, plus lisible, et plus facile Ă modifier : si le message d'initialisation change, on n'a qu'un seul endroit Ă modifier.
MĂȘme problĂšme, mais cette fois l'instruction rĂ©pĂ©tĂ©e se trouve Ă la fin de chaque bloc :
# Version redondante
masse_g = 5.2
volume_mL = 10.0
if masse_g > 0 and volume_mL > 0 :
densite = masse_g / volume_mL
print(f"Densité calculée : {densite} g/mL")
print("--- Fin de l'analyse ---") # â RĂ©pĂ©tĂ© Ă la fin des 2 blocs!
else :
print("â ïž ParamĂštres invalides, calcul impossible.")
print("--- Fin de l'analyse ---") # â RĂ©pĂ©tĂ© Ă la fin des 2 blocs!
# Version sans redondance
masse_g = 5.2
volume_mL = 10.0
if masse_g > 0 and volume_mL > 0 :
densite = masse_g / volume_mL
print(f"Densité calculée : {densite} g/mL")
else :
print("â ïž ParamĂštres invalides, calcul impossible.")
print("--- Fin de l'analyse ---") # â
Exécuté dans tous les cas aprÚs les 2 blocs
| Position de la redondance | Solution |
|---|---|
| Au début de chaque bloc | Placer l'instruction avant le bloc if |
| Ă la fin de chaque bloc | Placer l'instruction aprĂšs le bloc if/else |
| Au début et à la fin | Placer une instruction avant et une aprÚs |
đ La rĂšgle est simple : si une instruction s'exĂ©cute dans tous les cas, elle ne devrait jamais se retrouver Ă l'intĂ©rieur d'un if ou d'un else.
# Version redondante
pression_atm = 2.3
if pression_atm > 2.0 :
print("=== Rapport de pression ===") # â DĂ©but redondant
print("â ïž Pression critique dĂ©tectĂ©e!")
print("=== Fin du rapport ===") # â Fin redondante
else :
print("=== Rapport de pression ===") # â DĂ©but redondant
print("â
Pression dans les normes.")
print("=== Fin du rapport ===") # â Fin redondante
# Version sans redondance
pression_atm = 2.3
print("=== Rapport de pression ===") # â
Redondance déplacée avant les blocs
if pression_atm > 2.0 :
print("â ïž Pression critique dĂ©tectĂ©e!")
else :
print("â
Pression dans les normes.")
print("=== Fin du rapport ===") # â
Redondance déplacée aprÚs les blocs
Le résultat affiché est identique, mais la version propre est bien plus facile à lire et à maintenir!
Parfois, deux instructions se ressemblent mais ne sont pas identiques : elles ne peuvent donc pas ĂȘtre sorties du bloc.
# â
Ce n'est PAS de la redondance, car les messages sont différents!
ph = 4.2
if ph < 7 :
print(f"Le pH de {ph} indique une solution acide.")
else :
print(f"Le pH de {ph} indique une solution basique ou neutre.")
Ici, les deux print contiennent du texte différent. Ils doivent rester dans leurs blocs respectifs.
Les explications de cette section étaient-elles claires ?
Pour les instructions conditionnelles simples, on peut utiliser une forme compacte en une seule ligne.
Par exemple :
age = 20
print("Vous ĂȘtes majeur.") if age >= 18 else print("Vous ĂȘtes mineur.")
On peut aussi utiliser cette forme compacte pour stocker le résultat dans une variable :
age = 20
statut = "majeur" if age >= 18 else "mineur"
print(statut) # Affiche "majeur"
La forme compacte est utile pour des conditions simples et des actions courtes.
Cependant, pour des conditions plus complexes ou des blocs de code plus longs,
il est préférable d'utiliser la forme standard avec indentation pour une meilleure lisibilité.
On peut aussi utiliser des elif dans une forme compacte, mais cela peut rapidement devenir difficile Ă lire.
Par exemple :
score = 85
resultat = "Excellent" if score >= 90 else "Bien" if score >= 75 else "Passable" if score >= 50 else "Ăchec"
print(resultat) # Affiche "Bien"
Si on a besoin de elif, il est préférable d'utiliser la forme standard pour une meilleure lisibilité.
Les explications de cette section étaient-elles claires ?
Quand on écrit une fonction, il faut s'assurer que les entrées (paramÚtres) ont du sens.
Sinon, on risque d'obtenir des résultats absurdes ou des erreurs difficiles à comprendre.
Comparez ces deux versions :
# Version 1 â sans validation
def densite(masse, volume):
return masse / volume
print(densite(10, 2)) # â
5.0
print(densite(-3, 5)) # â ïž -0.6 g/mL sans avertissement (rĂ©sultat absurde), le programme continue malgrĂ© tout!
print(densite(8, 0)) # â Erreur Python brute (ZeroDivisionError), le programme arrĂȘte ici!
a = 1 + 2 # Cette instruction ne sera jamais exécutée.
# Version 2 â avec validation
def densite(masse, volume):
if masse < 0:
raise ValueError("La masse doit ĂȘtre positive.")
if volume <= 0:
raise ValueError("Le volume doit ĂȘtre supĂ©rieur Ă 0.")
return masse / volume
print(densite(10, 2)) # â
5.0
print(densite(-3, 5)) # â ValueError : La masse doit ĂȘtre positive, message clair, le programme arrĂȘte ici!
print(densite(8, 0)) # Cette instruction et les suivantes ne seront jamais exécutées.
a = 1 + 2
đ La version 2 donne des messages d'erreur explicites, Ă©vite les rĂ©sultats absurdes et rend le code plus robuste et rĂ©utilisable.
raise â mettre une barriĂšre dans une fonctionraise permet de provoquer volontairement une erreur si une condition n'est pas respectĂ©e.
C'est la façon de signaler au programmeur qui appelle la fonction qu'il l'utilise avec de mauvaises valeurs.
def concentration(masse_g, volume_L):
if masse_g < 0:
raise ValueError("La masse doit ĂȘtre positive.")
if volume_L <= 0:
raise ValueError("Le volume doit ĂȘtre supĂ©rieur Ă 0.")
return masse_g / volume_L
DÚs qu'une condition invalide est détectée, Python interrompt immédiatement la fonction et remonte l'erreur à l'appelant.
Les lignes suivantes à l'intérieur de la fonction ne sont jamais exécutées (comme c'est le cas avec l'instruction return).
try/except â mettre un filet de sĂ©curitĂ© Ă l'appeltry/except permet de rattraper une erreur qui se produit, plutĂŽt que de laisser le programme planter.
Exécutez ce code sans try/except, observez l'erreur, puis ajoutez le filet et relancez :
# Sans filet : le programme plante
print(concentration(4, 20)) # â
OK
print(concentration(-10, 20)) # â Le programme s'arrĂȘte ici avec une erreur brute
print(concentration(4, 5)) # Jamais atteint
# Avec filet : le programme gĂšre l'erreur proprement
try:
print(concentration(4, 20)) # â
Exécuté normalement
print(concentration(-10, 20)) # â LĂšve ValueError â on saute au except
print(concentration(4, 5)) # âïž Jamais atteint (on est dĂ©jĂ dans le except)
except ValueError as e:
print(f"Une erreur est survenue : {e}")
La variable e contient le message d'erreur personnalisé passé à raise.
On peut choisir de faire ce qu'on veut du message :
- l'afficher Ă la console
- le journaliser dans un fichier
- exécuter un bout de code en particulier en fonction du message
raise et try/except| MĂ©canisme | RĂŽle | OĂč l'Ă©crire |
|---|---|---|
| raise | Signaler un problĂšme (mettre une barriĂšre) | Dans la fonction, lĂ oĂč les paramĂštres sont vĂ©rifiĂ©s |
| try/except | Attraper un problĂšme (mettre un filet) | Ă l'appel de la fonction, pour gĂ©rer proprement les erreurs et Ă©viter l'arrĂȘt du programme |
đ On utilise raise pour protĂ©ger la fonction, et try/except pour que l'appelant dĂ©cide quoi faire en cas d'erreur.
Ce n'est pas seulement votre code qui peut lever des exceptions â les fonctions de la bibliothĂšque standard de Python le font aussi.
Comprendre quelles erreurs elles peuvent produire vous aide Ă les anticiper et mĂȘme les intercepter (avec un bloc try/except) pour Ă©viter l'arrĂȘt pur et simple du programme.
math â erreurs de domaine mathĂ©matique
import math
math.sqrt(25) # â
5.0
math.sqrt(-1) # â ValueError: math domain error (racine d'un nombre nĂ©gatif)
math.log(100) # â
4.605...
math.log(0) # â ValueError: math domain error (log(0) est indĂ©fini)
math.log(-5) # â ValueError: math domain error (log d'un nĂ©gatif)
math.factorial(5) # â
120
math.factorial(-1)# â ValueError: factorial() not defined for negative values
math.factorial(2.5)# â TypeError: 'float' object cannot be interpreted as an integer
đ Le module math lĂšve une ValueError dĂšs qu'on sort du domaine mathĂ©matique valide (valeur impossible Ă calculer).
int() et float() â erreurs de conversion
int("42") # â
42
int("3.14") # â ValueError: invalid literal for int() with base 10: '3.14'
int("abc") # â ValueError: invalid literal for int() with base 10: 'abc'
float("3.14") # â
3.14
float("abc") # â ValueError: could not convert string to float: 'abc'
đ int() et float() lĂšvent une ValueError si la chaĂźne de caractĂšres ne reprĂ©sente pas un nombre valide.
C'est une erreur trÚs fréquente quand on lit une saisie utilisateur ou des données provenant d'un fichier.
Intercepter ces erreurs avec try/except
Voici un exemple concret qui combine math et la conversion :
import math
def calculer_racine(valeur_texte):
try:
nombre = float(valeur_texte) # Peut lever ValueError si non numérique
resultat = math.sqrt(nombre) # Peut lever ValueError si nombre < 0
return resultat
except ValueError as e:
print(f"Erreur : {e}")
return None
#Toutes les instructions ci-dessous sont exécutées!
print(calculer_racine("25")) # â
5.0
print(calculer_racine("-4")) # â
La fonction gĂšre l'erreur pour Ă©viter l'arrĂȘt du programme et elle retourne None
print(calculer_racine("abc")) # â
La fonction gĂšre l'erreur pour Ă©viter l'arrĂȘt du programme et elle retourne None
a = 1 + 2 # Cette instruction est finalement exécutée!
đ Un seul bloc try/except attrape Ă la fois les erreurs de conversion et les erreurs de domaine, car les deux lĂšvent une ValueError.
L'appel de la fonction calculer_racine() ne causera jamais l'arrĂȘt du programme car les erreurs sont bien attrapĂ©es.
La fonction va soit retourner :
- soit une valeur valide
- soit la valeur None
Bonne pratique : lire la documentation avant d'utiliser une fonction
Les exemples ci-dessus ne sont pas une liste exhaustive â chaque fonction de Python peut avoir son propre comportement en cas d'erreur.
Avant d'utiliser une fonction inconnue, consultez sa documentation pour savoir quelles exceptions elle peut lever et dans quelles circonstances.
Par exemple, la page de documentation de math.sqrt indique explicitement qu'une ValueError est lev Ă©e si l'argument est nĂ©gatif. C'est cette information qui vous permet d'Ă©crire un try/except adaptĂ© â ni trop large (attraper des erreurs imprĂ©vues), ni trop Ă©troit (manquer un cas rĂ©el).
Quand vous intégrez une nouvelle fonction dans votre code, posez-vous toujours la question :
"Qu'est-ce qui pourrait mal se passer ici, et est-ce que ma fonction le gĂšre?"
isinstance)Pour une validation solide, on peut aussi vĂ©rifier que les paramĂštres sont du bon type avant mĂȘme de vĂ©rifier leur valeur.
def calculer_concentration(masse_g, volume_L):
if not isinstance(masse_g, (int, float)):
raise TypeError("La masse doit ĂȘtre un nombre (int ou float).")
if not isinstance(volume_L, (int, float)):
raise TypeError("Le volume doit ĂȘtre un nombre (int ou float).")
if masse_g < 0:
raise ValueError("La masse doit ĂȘtre positive.")
if volume_L <= 0:
raise ValueError("Le volume doit ĂȘtre supĂ©rieur Ă 0.")
return masse_g / volume_L
try:
print(calculer_concentration(10, 2)) # â
5.0
print(calculer_concentration(-5, 2)) # â LĂšve ValueError â on saute au except
print(calculer_concentration(10, 0)) # âïž Jamais atteint (on est dĂ©jĂ dans le except)
print(calculer_concentration(10, "a")) # âïž Jamais atteint (on est dĂ©jĂ dans le except)
except (TypeError, ValueError) as e:
print(f"Erreur : {e}")
La fonction isinstance(valeur, type) retourne True si la valeur est du type donné.
Par exemple : isinstance(5, int) â True, isinstance("5", int) â False.
On peut tester plusieurs types Ă la fois : isinstance(5, (int, float)) â True.
đ Remarquez l'ordre des vĂ©rifications : on valide d'abord les types, puis les valeurs. C'est important, car une valeur du mauvais type (comme une masse de type str) ne pourrait mĂȘme pas ĂȘtre comparĂ©e Ă 0 sans provoquer une erreur.
Nous nous limitons aux trois exceptions les plus courantes :
| Exception | Quand l'utiliser |
|---|---|
| ZeroDivisionError | Une division par zéro est tentée ou le dénominateur est nul |
| TypeError | Le type de la valeur transmise n'est pas celui attendu |
| ValueError | La valeur est du bon type mais ne respecte pas les contraintes (ex. : masse négative) |
- N'attrapez avec
exceptque les erreurs prĂ©vues â sinon on risque de cacher de vrais bogues. - Donnez toujours un message utile dans
raisepour que l'erreur soit facile Ă comprendre. - Validez d'abord le type, puis la valeur : une masse de type
strne peut mĂȘme pas ĂȘtre comparĂ©e Ă 0. - L'ordre des validations dans la fonction a de l'importance : vĂ©rifiez ce qui est le plus fondamental en premier.
Avant de retourner un résultat, votre fonction a-t-elle vérifié :
- â
Les types sont corrects (
int,float, etc.) ? - â Les domaines sont respectĂ©s (positif, non nul, dans un intervalle, etc.) ?
- â Les cas limites sont couverts (valeur nulle, nĂ©gative, vide, etc.) ?
Les explications de cette section étaient-elles claires ?
đ”ïžââïž Trace dâexĂ©cution avec des structures conditionellesâ
Voici un exemple de trace d'exécution contenant des structures conditionnelles
- Certaines lignes ne s'exécutent pas, c'est le principe de la condition!
- On indique les lignes qui testent une condition :
if,elif,match,case(mais paselsenicase _).
Codeâ
Si on a le code suivant :
a = 42
if a > 100:
print('a est grand')
elif a > 10:
print('a est moyen')
elif a > 1:
print('a est petit')
else:
print('a est trĂšs petit')
print('a est nul') if a == 0 else print('fin')
Traceâ
On aura la trace suivante :
| portée globale | |||||
|---|---|---|---|---|---|
| #ligne | a | affichage | pile d'appels | fonction appelée | valeur retournée |
| 1 | 42 | ||||
| 2 | 42 | ||||
| 4 | 42 | ||||
| 5 | 42 | a est moyen | |||
| 11 | 42 | fin | |||
Codeâ
Si on a le code suivant :
a = 42
match a:
case 6:
print('a est égal à 6')
case 7:
print('a est égal à 7')
case 42:
print('a est égal à 42')
case 420:
print('a est égal à 420')
case _:
print("a n'est pas 6, 7, 42 ou 420")
Traceâ
On aura la trace suivante :
| portée globale | |||||
|---|---|---|---|---|---|
| #ligne | a | affichage | pile d'appels | fonction appelée | valeur retournée |
| 1 | 42 | ||||
| 2 | 42 | ||||
| 3 | 42 | ||||
| 5 | 42 | ||||
| 7 | 42 | ||||
| 8 | 42 | a est égal à 42 | |||
Pour favoriser une progression efficace, ce cours adopte une approche de classe inversée. Ce modÚle déplace l'acquisition théorique hors de la classe pour transformer les heures de rencontre en véritables séances d'application pratique.
-
Ă la maison (Exploration et Appropriation) : Vous ĂȘtes le maĂźtre de votre rythme. Ces activitĂ©s vous permettent de dĂ©couvrir les nouveaux concepts et tester les exemples au moment oĂč vous ĂȘtes le plus concentrĂ©. Si une notion vous semble obscure, n'hĂ©sitez pas Ă poser des questions Ă votre prof au fur et Ă mesure.
-
En classe (Application et Consolidation) : Le temps en prĂ©sentiel est une ressource prĂ©cieuse. Nous l'utilisons pour nous attaquer aux dĂ©fis plus complexes et aux exercices de programmation qui demandent une mobilisation active de vos connaissances. Câest le moment idĂ©al pour obtenir une rĂ©troaction immĂ©diate, collaborer avec vos pairs et bĂ©nĂ©ficier de l'accompagnement de votre enseignant au moment oĂč vous en avez le plus besoin.
- đ ActivitĂ©s Ă faire Ă la maison
- đ« ActivitĂ©s Ă faire en classe
đ§ Auto-validation des connaissancesâ
Ce formulaire sert à vérifier votre compréhension des éléments les plus importants de la rencontre R04. Ne faites ce questionnaire que lorsque vous vous sentez en trÚs bonne maßtrise de la matiÚre. En classe, dÚs votre arrivée, vous aurez un questionnaire trÚs similaire, évalué sommativement, à compléter sans accÚs à aucune documentation.
Ne pas remplir le formulaire diminue fortement vos chances de rĂ©ussir lâĂ©valuation sommative en dĂ©but de rencontre.
Assurez-vous de bien comprendre toutes les notions derriĂšre chaque question.
âïž Exercices de comprĂ©hensionâ
Pour faire les traces des exercices suivants, regardez d'abord cette recette de trace avec condition
if/else + forme compacteđš Pour rĂ©aliser cet exercice, imprimez le tableau de trace d'exĂ©cution.
En situation d'examen, vous devrez compléter une trace d'exécution sur papier sans utiliser d'ordinateur.
Sans exécuter le code, déterminez ce que le programme ci-dessous va afficher dans la console.
En suivant les recettes de trace avec fonctions et avec conditions, complétez le tableau de trace d'exécution ligne par ligne.
def carre(x):
return x * x
def calcul(n):
if n % 2 == 0:
return n + 5
else:
return carre(n) - 1
x = 3
x = calcul(x)
if x >= 5:
calcul(x)
print("Hello World") if x == 13 else print("Fin")
Validez ensuite votre trace en exécutant le programme en mode débogage.
Avancez pas à pas et observez l'évolution de chaque variable à chaque ligne.
Structures conditionnelles (if/else), définition et appel de fonctions, return, opérateur modulo (%), forme compacte (ternaire), trace d'exécution, débogueur
if/elif/elifđš Pour rĂ©aliser cet exercice, imprimez le tableau de trace d'exĂ©cution.
Sans exécuter le code, déterminez ce que le programme ci-dessous va afficher dans la console.
En suivant les recettes de trace avec fonctions et avec conditions, complétez le tableau de trace d'exécution ligne par ligne.
def mystere(n):
if n % 2 == 0:
print("!")
elif n >= 10:
print("E")
if n // 10 == 5:
print("X")
print("P")
elif n >= 20:
print("F")
mystere(55)
print("33!")
Validez ensuite votre trace en exécutant le programme en mode débogage.
Avancez pas à pas et observez l'évolution de chaque variable à chaque ligne.
Structures conditionnelles (if/elif), conditions imbriquées, opérateurs (%, //, comparaisons), trace d'exécution, débogueur
and et orđš Pour rĂ©aliser cet exercice, imprimez le tableau de trace d'exĂ©cution.
Sans exécuter le code, déterminez ce que le programme ci-dessous va afficher dans la console.
En suivant les recettes de trace avec fonctions et avec conditions, complétez le tableau de trace d'exécution ligne par ligne.
def mystere(x, y, z):
if (x >= 5 or y < 15) and z >= 10:
print("Cas 1")
if (x >= 5 and y < 15) or z >= 10:
print("Cas 2")
mystere(0, 15, 15)
mystere(5, 10, 15)
Validez ensuite votre trace en exécutant le programme en mode débogage.
Avancez pas à pas et observez l'évolution de chaque variable à chaque ligne.
Opérateurs logiques (and, or), opérateurs de comparaison, structures conditionnelles, priorité des opérateurs (parenthÚses), trace d'exécution, débogueur
đŻ Solutionnaires
Consultez le solutionnaire uniquement aprĂšs avoir complĂ©tĂ© l'exercice par vous-mĂȘme.
Comparer votre réponse avec une solution vous permet de valider votre raisonnement et de corriger vos erreurs.
Consulter la solution avant d'avoir tenté l'exercice prive votre cerveau de l'occasion de construire des connexions durables.
- Trace avec
if/else+ forme compacte â solutionnaire.pdf - Trace avec
if/elif/elifâ solutionnaire.pdf - Trace avec opĂ©rateurs
andetorâ solutionnaire.pdf
đš Exercices de crĂ©ationâ
Pour chacun des exercices de cette section, vous devez créer des fichiers .py avec les noms indiqués.
Pour les exercices de cette section, vous pouvez consulter librement la documentation du site web du cours.
đ CrĂ©ez un fichier r04_niveau_ph.py pour votre rĂ©ponse.
Définissez une fonction décrivant le niveau d'acidité d'une solution à partir de son pH.
La fonction doit recevoir en entrée le pH et renvoyer en sortie soit : "acide", "neutre" ou "basique".
Validez le bon fonctionnement en testant les différents cas possibles à l'aide d'appels :
print(f"Une solution avec un Ph de 5 est : {nom_de_votre_fonction(5)}")
print(f"Une solution avec un Ph de 7 est : {nom_de_votre_fonction(7)}")
print(f"Une solution avec un Ph de 10 est : {nom_de_votre_fonction(10)}")
Définition de fonction, paramÚtre, structures conditionnelles (if/elif/else), return, f-strings
đ CrĂ©ez un fichier r04_analyse_echantillons.py pour votre rĂ©ponse.
Reprenez votre fonction niveau_ph de l'exercice précédent et utilisez-la pour analyser une série d'échantillons stockés dans des listes parallÚles.
Vous ne devez pas modifier le code de la fonction niveau_ph, vous devez la réutiliser telle quelle.
echantillons = ["Eau distillée", "Jus de citron", "Eau de mer", "Lait", "Soude caustique"]
ph_valeurs = [7.0, 2.4, 8.1, 6.7, 13.5]
Affiche l'analyse de chaque échantillon selon ce format :
â Sortie attendue
Eau distillĂ©e (pH 7.0) â neutre
Jus de citron (pH 2.4) â acide
Eau de mer (pH 8.1) â basique
Lait (pH 6.7) â acide
Soude caustique (pH 13.5) â basique
đ Pour obtenir les colonnes bien alignĂ©es, consultez la section Alignement de l'aide-mĂ©moire sur les f-strings
      en particulier la syntaxe :<N pour aligner un texte à gauche sur N caractÚres.
Listes parallĂšles, accĂšs par index, appel de fonction, f-strings
đ CrĂ©ez un fichier r04_refactorisation_bulletins.py pour votre rĂ©ponse.
Le code ci-dessous affiche un mini-bulletin pour un.e étudiant.e.
Il fonctionne correctement, mais il est truffé de répétitions inutiles dans les blocs if/elif/else.
Votre mission : le réécrire proprement en appliquant le principe DRY.
nom = "Félix"
note = 72
if note >= 90:
print("=== Bulletin scolaire ===")
print(f"Ătudiant : {nom}")
print(f"Note : {note} %")
print("Mention : Excellent")
print("Félicitations!")
print("=========================")
elif note >= 75:
print("=== Bulletin scolaire ===")
print(f"Ătudiant : {nom}")
print(f"Note : {note} %")
print("Mention : Bien")
print("Félicitations!")
print("=========================")
elif note >= 60:
print("=== Bulletin scolaire ===")
print(f"Ătudiant : {nom}")
print(f"Note : {note} %")
print("Mention : Passable")
print("Bonne continuation.")
print("=========================")
else:
print("=== Bulletin scolaire ===")
print(f"Ătudiant : {nom}")
print(f"Note : {note} %")
print("Mention : Ăchec")
print("Bonne continuation.")
print("=========================")
đ ïž INSTRUCTIONSâ
-
Identifiez toutes les instructions redondantes dans le code ci-dessus :
Comptez combien de fois chaqueprintapparaĂźt. Lesquels se retrouvent dans les 4 blocs? Lesquels varient d'un bloc Ă l'autre? -
Créez une fonction
afficher_bulletin(nom, note)qui réécrit ce code proprement, sans répétition.
Validez votre fonction avec ces deux appels :afficher_bulletin("Félix", 72)afficher_bulletin("Dayron", 91)
â Sortie attendue
=== Bulletin scolaire ===
Ătudiant : FĂ©lix
Note : 72 %
Mention : Passable
Bonne continuation.
=========================
=== Bulletin scolaire ===
Ătudiant : Dayron
Note : 91 %
Mention : Excellent
Félicitations!
=========================
Refactorisation (principe DRY), structures conditionnelles (if/elif/else), définition de fonction, f-strings
đ CrĂ©ez un fichier r04_classification_sismique.py pour votre rĂ©ponse.
Lors d'un tremblement de terre, deux mesures sont enregistrées : la magnitude (énergie libérée, échelle de Richter) et la profondeur du foyer en kilomÚtres. Ces deux valeurs, analysées ensemble, permettent d'estimer l'impact en surface.
On veut écrire un programme qui affiche une fiche sismique complÚte à partir de ces deux mesures.
đ DonnĂ©es de rĂ©fĂ©renceâ
Classification par magnitude :
| Magnitude | Catégorie |
|---|---|
| < 2.0 | Micro |
| < 4.0 | Mineur |
| < 6.0 | Modéré |
| < 7.0 | Fort |
| â„ 7.0 | Majeur |
Classification par profondeur du foyer :
| Profondeur (km) | Type de foyer |
|---|---|
| †70 | Superficiel |
| †300 | Intermédiaire |
| > 300 | Profond |
Impact probable (dépend des deux paramÚtres combinés) :
| Magnitude | Profondeur | Impact probable |
|---|---|---|
| < 4.0 | peu importe | Généralement non ressenti ou ressenti légÚrement. |
| < 6.0 | †70 km | Ressenti clairement, légers dégùts possibles prÚs de l'épicentre. |
| < 6.0 | > 70 km | Ressenti faiblement en surface, peu de dégùts. |
| < 7.0 | †70 km | Dommages importants prÚs de l'épicentre, ressenti sur une large zone. |
| < 7.0 | > 70 km | Ressenti sur une large zone, dommages modérés en surface. |
| ℠7.0 | †70 km | Dommages majeurs, potentiellement catastrophique prÚs de l'épicentre. |
| ℠7.0 | > 70 km | Dommages importants malgré la profondeur, ressenti trÚs largement. |
đ ïž INSTRUCTIONSâ
-
Créez une fonction
classifier_magnitude(magnitude)qui retourne la catégorie correspondante ("Micro","Mineur","Modéré","Fort"ou"Majeur"). -
Créez une fonction
classifier_profondeur(profondeur_km)qui retourne le type de foyer ("Superficiel","Intermédiaire"ou"Profond"). -
Créez une fonction
impact_probable(magnitude, profondeur_km)qui retourne la description de l'impact en combinant les deux paramĂštres.
đ Deux approches sont possibles pour cette fonction :- Conditions imbriquĂ©es : on Ă©value d'abord la magnitude, puis on affine selon la profondeur Ă l'intĂ©rieur de chaque bloc (
ifdans unif). - Conditions combinées avec
and: on teste les deux critĂšres sur une mĂȘme ligne.
- Conditions imbriquées : on évalue d'abord la magnitude, puis on affine selon la profondeur à l'intérieur de chaque bloc (
-
Créez une fonction
afficher_fiche(magnitude, profondeur_km)qui appelle les trois fonctions précédentes et affiche la fiche selon le format ci-dessous.
Validez votre programme avec les 4 cas ci-dessous.
â
Cas 1 (magnitude = 3.2, profondeur_km = 50)
=== Fiche sismique ===
Magnitude : 3.2
Profondeur : 50 km
Catégorie : Mineur
Foyer : Superficiel
Impact : Généralement non ressenti ou ressenti légÚrement.
======================
â
Cas 2 (magnitude = 5.1, profondeur_km = 30)
=== Fiche sismique ===
Magnitude : 5.1
Profondeur : 30 km
Catégorie : Modéré
Foyer : Superficiel
Impact : Ressenti clairement, légers dégùts possibles prÚs de l'épicentre.
======================
â
Cas 3 (magnitude = 6.2, profondeur_km = 150)
=== Fiche sismique ===
Magnitude : 6.2
Profondeur : 150 km
Catégorie : Fort
Foyer : Intermédiaire
Impact : Ressenti sur une large zone, dommages modérés en surface.
======================
â
Cas 4 (magnitude = 7.8, profondeur_km = 20)
=== Fiche sismique ===
Magnitude : 7.8
Profondeur : 20 km
Catégorie : Majeur
Foyer : Superficiel
Impact : Dommages majeurs, potentiellement catastrophique prÚs de l'épicentre.
======================
Définition de fonctions, paramÚtres, return, structures conditionnelles (if/elif/else), conditions imbriquées, appel d'une fonction depuis une autre, f-strings
đ CrĂ©ez un fichier r04_tarification_electrique.py pour votre rĂ©ponse.
Hydro-Québec facture l'électricité résidentielle selon un systÚme de paliers :
les premiers kilowattheures consommés coûtent moins cher, et la consommation supplémentaire est facturée à un tarif plus élevé.
Voici une version simplifiée des tarifs :
| Tarif | Palier | Prix |
|---|---|---|
| Tarif D (régulier) | Premiers 40 kWh/jour | 0,06 $/kWh |
| Tarif D (régulier) | Au-delà de 40 kWh/jour | 0,10 $/kWh |
| Tarif nuit (uniforme) | Toute la consommation | 0,05 $/kWh |
- Les premiers 40 kWh : 40 Ă 0,06 = 2,40 $
- Les 25 kWh restants (65 â 40) : 25 Ă 0,10 = 2,50 $
- Total : 4,90 $
đ La clĂ© : quand kwh > 40, la facture se calcule en deux parties. On paie les 40 premiers kWh au tarif bas, puis le surplus au tarif Ă©levĂ©.
đ ïž INSTRUCTIONSâ
-
Créez une fonction
calculer_facture(kwh, tarif_nuit=False)qui calcule et retourne le montant Ă payer.
Le paramÚtretarif_nuit=Falseest optionnel : par défaut, on utilise le tarif D.
Si on passeTrue, on utilise le tarif nuit uniforme.
Validez avec ces appels avant de passer Ă la suite :print(calculer_facture(30)) # Tarif D, 30 kWh â 1.8print(calculer_facture(65)) # Tarif D, 65 kWh â 4.9print(calculer_facture(65, True)) # Tarif nuit â 3.25 -
Créez une fonction
afficher_comparaison(nom_client, kwh)qui appellecalculer_facturedeux fois :
une fois sans argument optionnel (tarif D), une fois avecTrue(tarif nuit) et affiche ensuite la comparaison dans la console.
Validez avec cet appel :afficher_comparaison("Euclide", 65)â Sortie attendue :
Client : Euclide (65 kWh)Tarif D : 4.90 $Tarif nuit : 3.25 $
Structures conditionnelles (paliers), définition de fonctions, paramÚtre avec valeur par défaut, return, appel d'une fonction depuis une autre
đ CrĂ©ez un fichier r04_quidditch.py pour votre rĂ©ponse.
La saison de Quidditch de Poudlard est terminée!
Les résultats des quatre maisons ont été compilés et sont déjà classés du premier au dernier.
Votre mission : afficher le classement officiel.
maisons = ["Gryffondor", "Serpentard", "Serdaigle", "Poufsouffle"]
victoires = [3, 2, 1, 0]
defaites = [0, 1, 2, 3]
points = [450, 320, 280, 150]
â Sortie attendue
ââââââââââââââââââââââââââââââââââââââââââââ
â Tournoi de Quidditch de Poudlard â
ââââââââââââââââââââââââââââââââââââââââââââ
1. Gryffondor - 3V / 0D - 450 pts ** Coupe des Quatre Maisons! **
2. Serpentard - 2V / 1D - 320 pts
3. Serdaigle - 1V / 2D - 280 pts
4. Poufsouffle - 0V / 3D - 150 pts [ Retourne a lâentrainement! ]
ââââââââââââââââââââââââââââââââââââââââââ
Contraintes :
- Définissez une fonction
afficher_maisonqui affiche la ligne de classement d'une seule maison. - Définissez une fonction
afficher_classementqui affiche l'en-tĂȘte, appelleafficher_maisonpour chaque maison, et affiche le sĂ©parateur final. - Le programme doit fonctionner peu importe les valeurs dans les listes. Elles auront toujours 4 Ă©lĂ©ments.
- La premiÚre et la derniÚre maison du classement ont un message spécial.
đ Pour obtenir les colonnes bien alignĂ©es, consultez la section Alignement de l'aide-mĂ©moire sur les f-strings
      en particulier la syntaxe :<N pour aligner un texte à gauche sur N caractÚres.
DĂ©finition de fonctions, paramĂštres, return, structures conditionnelles (if/elif/else), listes parallĂšles, accĂšs par index, f-strings, appel dâune fonction depuis une autre
đ CrĂ©ez un fichier r04_validation_parametres.py pour votre rĂ©ponse.
Ăcrivez une fonction densite(masse, volume) qui calcule et retourne la densitĂ© en g/mL selon la formule :
oĂč est la masse en grammes (g) et le volume en millilitres (mL).
- Validez que la masse est positive.
- Validez que le volume est strictement positif (non nul).
- Levez une exception claire (
ValueErrorouZeroDivisionError) si les conditions ne sont pas respectées.
Testez votre fonction en l'appelant avec des valeurs valides et invalides pour vérifier que la validation fonctionne correctement.
Pourquoi est-il prĂ©fĂ©rable d'arrĂȘter l'exĂ©cution avec un message clair plutĂŽt que de laisser Python planter avec une erreur brute?
Définition de fonction, paramÚtres, return, validation de paramÚtres avec conditions, levée d'exceptions (raise, ValueError, ZeroDivisionError)
âïž Exercices sur papierâ
Faites ces exercices d'abord sur papier (ou dans un éditeur de texte simple) et sans aucune documentation, comme à l'examen.
Vous pouvez valider votre rĂ©ponse dans PyCharm Ă la fin â un luxe que vous n'aurez pas le jour de l'examen, d'oĂč l'importance de vous entraĂźner sans lui.
đ CrĂ©ez un fichier r04_imc.py pour votre rĂ©ponse.
Ăcrivez un programme qui calcule et interprĂšte l'indice de masse corporelle (IMC) d'une personne selon la formule :
Interprétation :
| IMC | Catégorie |
|---|---|
| < 18.5 | Insuffisance pondérale |
| < 25.0 | Poids normal |
| < 30.0 | Surpoids |
| ℠30.0 | Obésité |
Contraintes techniques :
- Définissez une fonction
calculer_imc(masse, taille)qui retourne l'IMC arrondi à 1 décimale. - Définissez une fonction
interpreter_imc(imc)qui retourne la catégorie correspondante (elle ne doit pas faire deprint). - Affichez le résultat selon le format ci-dessous.
Le début de votre programme est le suivant :
masse = 70 # en kg
taille = 1.75 # en mĂštres
Exemple attendu :
Masse : 70 kg
Taille : 1.75 m
IMC : 22.9
Catégorie : Poids normal
Définition de fonctions, paramÚtres, return, structures conditionnelles (if/elif/else), opérateurs arithmétiques (**), format à 1 décimale
đŻ Solutions des exercices
Un solutionnaire possible pour chaque exercice est disponible en format vidĂ©o avec des explications. Vous pouvez vous en servir pour comparer votre solution avec une solution possible jugĂ©e optimale et vous dĂ©bloquer aprĂšs un long moment bloquĂ© sur un exercice (ex. 20 minutes) et aprĂšs avoir utilisĂ© le dĂ©bogueur pour essayer par vous-mĂȘme de trouver le problĂšme.
Il est tout Ă fait normal que certains problĂšmes demandent du temps, de la rĂ©flexion, et parfois mĂȘme un peu de frustration. Câest prĂ©cisĂ©ment dans ces moments dâeffort que lâapprentissage sâancre rĂ©ellement.
Consulter un solutionnaire avant dâavoir tentĂ© lâexercice par soi-mĂȘme, ou le parcourir trop rapidement, revient Ă court-circuiter le processus dâapprentissage. Ce nâest pas simplement contre-productif, câest pĂ©dagogiquement dĂ©sastreux.
En sautant lâĂ©tape de la rĂ©flexion personnelle, on prive son cerveau de lâoccasion de construire des connexions durables. Et Ă force de rĂ©pĂ©ter ce rĂ©flexe, on risque de passer Ă cĂŽtĂ© des compĂ©tences essentielles, ce qui peut mener Ă des Ă©checs plus tard, mĂȘme si tout semble facile sur le moment. Alors oui, prenez le temps. Lâerreur fait partie du jeu. Câest en cherchant, en tĂątonnant, en doutant, quâon devient rĂ©ellement compĂ©tent. Le solutionnaire doit ĂȘtre un outil de validation, pas un raccourci.
đš Solution des exercices de crĂ©ation :
- Le niveau de pH
- Analyse d'échantillons chimiques
- Refactorisation : les bulletins scolaires
- Classification sismique
- Tarification électrique par paliers
- Tournoi de Quidditch
- Validation de paramĂštres
âïž Solution des exercices sur papier :
La structure match/case produit des résultats trÚs similaires à un if/elif/else enchaßné.
Elle n'est pas exigée dans ce cours : tu ne seras jamais évalué dessus.
Si tu la trouves intuitive, libre Ă toi de l'utiliser. Un bon vieux if/elif/else fera toujours l'affaire!
Le match/case est une structure de contrĂŽle qui permet de faire des correspondances de motifs (pattern matching).
- Il permet de comparer une variable Ă plusieurs valeurs possibles.
- Il offre ainsi une alternative aux longues chaĂźnes d'instructions
if/elif/elsepour des cas spécifiques.
Sa syntaxe est la suivante :
match variable:
case valeur1:
# code à exécuter si variable == valeur1
case valeur2:
# code à exécuter si variable == valeur2
case _:
# code à exécuter si aucune des valeurs précédentes ne correspond
- Le
_dans le derniercaseagit comme unelse, capturant tous les autres cas non spĂ©cifiĂ©s. - Utile pour des comparaisons simples, mais peut ĂȘtre moins flexible que
if/elif/elsepour des conditions complexes. - Exemple :
jour = "lundi"
match jour:
case "lundi":
print("Début de la semaine")
case "mercredi":
print("Milieu de la semaine")
case "vendredi":
print("Fin de la semaine")
case _:
print("Jour ordinaire")
- Plus lisible pour des comparaisons multiples sur une mĂȘme variable.
- Permet de gérer facilement des cas spécifiques.
- Peut ĂȘtre plus performant que de nombreuses instructions
if/elifdans certains cas.
đ Il est important de noter que tout match/case peut ĂȘtre réécrit avec des if/elif/else, mais l'inverse n'est pas toujours vrai.
Les explications de cette section étaient-elles claires ?