Semaine 2 : Structures de contrôle
🎯 Objectifs d'apprentissage
À la fin de cette semaine, vous serez capable de :
- Ramifier le comportement d'un programme avec
if/elif/else. - Combiner des conditions avec
and,oretnot. - Répéter des actions avec les boucles
whileetfor, et choisir la bonne. - Utiliser
range()pour boucler un nombre fixe de fois, etbreak/continuepour contrôler une boucle en avance. - Imbriquer boucles et conditions pour résoudre des problèmes comportant plusieurs éléments variables.
Cours
La ramification : if / elif / else
Une instruction if est une définition par morceaux. Comparez :
x = -3
if x < 0:
print("negative")
elif x == 0:
print("zero")
else:
print("positive")
L'indentation n'est pas ici une simple question de style — elle est la syntaxe. Tout ce qui est indenté sous if appartient à cette branche ; Python n'a pas de { } pour délimiter les blocs. Un bloc a besoin d'au moins une instruction — si vous voulez une branche qui ne fait volontairement rien (par exemple lorsque vous esquissez la structure d'un programme avant de le remplir), utilisez pass, une instruction dont le seul rôle est de ne rien faire :
if x < 0:
pass # TODO: handle negative numbers later
else:
print("non-negative")
Combiner des conditions : and, or, not
Tout comme , , en logique, Python dispose de and, or, not pour combiner des expressions booléennes :
age = 20
has_ticket = True
if age >= 18 and has_ticket:
print("Welcome in")
if age < 13 or age > 65:
print("Discount applies")
if not has_ticket:
print("Buy a ticket first")
Elles suivent les mêmes tables de vérité que vous attendez : and est vrai seulement quand les deux côtés sont vrais ; or est vrai quand au moins un côté est vrai ; not inverse un booléen. Python pratique aussi l'évaluation en court-circuit : dans a and b, si a est déjà False, Python n'évalue même jamais b, puisque l'expression entière doit être False quoi qu'il arrive. Cela compte lorsque l'évaluation de b pourrait être coûteuse ou dangereuse — par exemple x != 0 and 10 / x > 1 ne risque jamais de diviser par zéro, car si x != 0 vaut False, la division est entièrement sautée.
while : répéter jusqu'à ce qu'une condition échoue
Une boucle while est ce qui se rapproche le plus d'une relation de récurrence mathématique avec une condition d'arrêt :
n = 5
while n > 0:
print(n)
n = n - 1
print("liftoff!")
Ceci affiche 5 4 3 2 1 liftoff!. La boucle revérifie n > 0 avant chaque itération — si vous oubliez de mettre à jour n à l'intérieur de la boucle, elle ne devient jamais fausse, et vous obtenez une boucle infinie.
while est l'outil approprié quand vous ne connaissez pas à l'avance le nombre d'itérations nécessaires — la condition d'arrêt dépend de quelque chose qui se produit pendant la boucle, comme une saisie utilisateur ou une recherche pouvant se terminer plus tôt :
guess = None
target = 42
while guess != target:
guess = int(input("Guess the number: "))
print("Correct!")
for : répéter sur une séquence connue
Une boucle for parcourt directement une séquence de valeurs — pensez-y comme à où est ce que vous parcourez, sauf que vous exécutez du code pour chaque au lieu d'additionner des nombres :
for letter in "cat":
print(letter) # c, a, t — un par ligne
range(n) produit la séquence — exactement l'ensemble d'indices que vous utiliseriez pour :
total = 0
for i in range(5):
total = total + i
print(total) # 0+1+2+3+4 = 10
range(start, stop) et range(start, stop, step) généralisent cela, en reflétant une suite arithmétique :
for i in range(2, 10, 2):
print(i) # 2, 4, 6, 8 — commence à 2, s'arrête avant 10, pas de 2
Un pas négatif compte à rebours : range(5, 0, -1) produit 5, 4, 3, 2, 1, la même séquence que l'exemple de compte à rebours en while de la Semaine 1, construite à la main.
break et continue
break quitte immédiatement une boucle ; continue passe à l'itération suivante sans terminer l'itération en cours :
for i in range(10):
if i == 5:
break # stop entirely once i reaches 5
if i % 2 == 0:
continue # skip printing even numbers
print(i) # prints 1, 3
Imbrication : boucles et conditions les unes dans les autres
Le corps d'une boucle — ou une branche if — peut contenir une autre boucle ou un autre if, exactement comme les cas d'une fonction définie par morceaux peuvent eux-mêmes comporter des conditions supplémentaires. Chaque niveau d'imbrication ajoute un niveau d'indentation supplémentaire :
for row in range(1, 4):
for col in range(1, 4):
print(row * col, end=" ") # end=" " prints a space instead of a newline
print() # move to the next line after each row
Ceci affiche une petite table de multiplication 3×3 :
1 2 3
2 4 6
3 6 9
La boucle interne s'exécute entièrement à chaque itération de la boucle externe — pour 3 itérations externes et 3 itérations internes chacune, cela fait instructions d'affichage au total, le même principe de comptage qui sous-tend une double somme .
⚠️ Pièges courants
- Erreurs de décalage d'un cran avec
range.range(1, 10)s'arrête avant 10, ce qui donne1..9. Si vous voulez inclure 10, il vous fautrange(1, 11). - Oublier de mettre à jour la variable de boucle dans un
while.while n > 0: print(n)sansn -= 1à l'intérieur ne se termine jamais. - Utiliser
=au lieu de==dans une condition. Python détecte en fait cette erreur pour vous (if x = 5:déclenche uneSyntaxError), contrairement à certains autres langages — mais il reste utile de comprendre pourquoi ce serait un bug si c'était autorisé. - Supposer que les chaînes
elifvérifient toutes les branches. Dès qu'une conditionelif/ifcorrespond, le reste est entièrement sauté — l'ordre compte, en particulier pour des conditions qui se chevauchent comme le cas « divisible à la fois par 3 et par 5 » de FizzBuzz.
🧩 Défis
Écrivez « FizzBuzz » pour les nombres de 1 à 10 : affichez "Fizz" si divisible par 3, "Buzz" si divisible par 5, "FizzBuzz" si divisible par les deux, sinon le nombre lui-même.
Écrivez une boucle qui continue de demander "Type 'quit' to stop: " jusqu'à ce que l'étudiant tape exactement quit. for ou while conviendrait-il mieux à cette tâche, et pourquoi ?
Additionnez les entiers de 1 à 100 à l'aide d'une boucle, et vérifiez la réponse de votre programme par rapport à la formule fermée .
Écrivez un programme qui lit un nombre n et affiche s'il est premier, en vérifiant si un entier quelconque de 2 jusqu'à (mais sans l'inclure) n le divise exactement.
À l'aide de boucles imbriquées, affichez un carré d'astérisques, n lignes sur n colonnes, pour un nombre n de votre choix (par exemple un bloc 4×4 de caractères *).
Écrivez une condition utilisant and qui vérifie si une variable age est comprise entre 18 et 65 (18 inclus, 65 exclu) et qu'un booléen has_ticket vaut True.
🤔 Questions socratiques
- Que se passe-t-il si vous écrivez
while True:sansbreakà l'intérieur ? Essayez prudemment dans le bac à sable (vous devrez peut-être arrêter l'exécution manuellement) — pourquoi cela diffère-t-il d'une boucleforsur unrangefixe ? - Dans FizzBuzz, pourquoi le cas divisible par les deux (
FizzBuzz) doit-il être vérifié avant les vérifications séparéesFizz/Buzz, ou géré avecand? Que se passerait-il de travers avec un ordreelifnaïf ? for i in range(5):eti = 0; while i < 5: ...; i += 1font la même chose. Dans quelles circonstances seriez-vous obligé d'utiliserwhileparce queforne peut vraiment pas l'exprimer ?- L'évaluation en court-circuit signifie que
a and bsaute l'évaluation debsiavaut déjàFalse. Pouvez-vous imaginer une situation (au-delà de l'exemple de la division par zéro ci-dessus) où cela compte pour plus qu'une simple question de performance — où évaluerbalors qu'il ne devrait pas l'être serait réellement incorrect, et pas seulement du gaspillage ? - L'exemple de la table de multiplication imbrique un
fordans unfor. À quoi ressemblerait l'imbrication d'unwhiledans unfor, et pouvez-vous imaginer une tâche réelle (pas juste un exemple inventé) où cette combinaison serait le choix naturel ?