Conditions et boucles
Jusqu'ici, les programmes se lisaient de haut en bas, ligne après ligne, toujours dans le même ordre. Ce chapitre change cela : le programme va se mettre à décider et à répéter.
On a déjà vu ces idées en algorithmique, sous la forme « Si / Alors / Sinon » et « Tant que ». Python reprend exactement la même logique. C'est le chapitre le plus important du cours : ces deux mécanismes sont dans absolument tous les programmes qu'on écrira.
Ce qu'on va apprendre
- Prendre une décision avec
if,elifetelse. - Comprendre pourquoi une suite de
ifne fait pas la même chose qu'unelif. - Répéter avec
foret avecwhile, et savoir lequel choisir. - Éviter les trois pièges classiques :
=au lieu de==,ormal écrit, boucle infinie.
La première décision
Un programme qui décide, cela ressemble à ceci. Exécuter, puis change la valeur de age.
Deux lignes s'affichent seulement quand la condition est vraie, une troisième s'affiche toujours. Regardons bien pourquoi : les deux premières sont décalées vers la droite, la dernière non.
L'indentation, la règle d'or
L'indentation est le décalage d'une ligne vers la droite. En Python, elle n'est pas décorative : c'est elle, et elle seule, qui dit quelles lignes appartiennent au bloc.
Là où d'autres langages emploient des accolades, Python emploie l'espace. La convention est de quatre espaces par niveau. Ce qui est décalé sous le if ne s'exécute que si la condition est vraie ; ce qui revient à gauche s'exécute dans tous les cas.
À faire. Dans le bloc précédent, décale print("Fin du programme.") de quatre espaces vers la droite, mets age = 15, et relance. La ligne ne s'affiche plus : elle est devenue une ligne du if.
Le bloc suivant est faux exprès : l'indentation manque.
IndentationError: expected an indented block. Traduction : Python a lu les deux points, il attend donc un bloc décalé, et il n'en trouve pas.
Choisir entre plusieurs cas
else couvre tout ce que le if n'a pas pris. elif, contraction de « else if », ajoute un cas intermédiaire.
Python teste dans l'ordre et s'arrête à la première condition vraie. Les suivantes ne sont même pas évaluées.
if ne fait pas la même chose qu'un elifExécutons ce bloc, qui attribue une mention à une note de 15.
Deux lignes s'affichent. Les trois if sont indépendants : chacun est évalué, et les deux premiers sont vrais. Ce n'est pas ce qu'on voulait.
À faire. Remplacer les deuxième et troisième if par des elif, puis inverse l'ordre en mettant note >= 16 en premier. Relance : une seule mention s'affiche, la bonne. Avec elif, l'ordre décide de tout.
Comparer
| Opérateur | Sens | Exemple | Résultat |
|---|---|---|---|
== | égal à | 5 == 5 | True |
!= | différent de | 3 != 4 | True |
< <= | inférieur, inférieur ou égal | 3 <= 3 | True |
> >= | supérieur, supérieur ou égal | 8 >= 9 | False |
Un test renvoie toujours un booléen, True ou False. On peut l'afficher directement, c'est un bon moyen de vérifier une condition compliquée avant de la mettre dans un if.
Le bloc suivant est faux exprès : il confond affectation et comparaison.
SyntaxError: invalid syntax. Rappelons-nous le chapitre 2 : = colle une étiquette, c'est une action. == compare, c'est une question. Dans un if, on pose une question.
Combiner plusieurs conditions
and exige que les deux soient vraies, or qu'au moins une le soit, not inverse.
if choix == 1 or 2:, et cette condition est toujours vraie, quelle que soit la valeur de choix.Python lit en effet
(choix == 1) or (2). Or le nombre 2 n'est pas nul, donc il vaut True, comme on l'a vu au chapitre 2 avec bool(2). Un or dont un côté est toujours vrai est toujours vrai.Il faut répéter la variable de chaque côté :
if choix == 1 or choix == 2:
Le vérifier soi-même : le premier test devrait être faux, et pourtant.
Il existe une écriture plus courte et plus sûre, qu'on peut employer dès maintenant : if choix in (1, 2):.
Répéter un nombre connu de fois : for
La boucle for répète un bloc pour chaque élément d'une suite de valeurs. On l'emploie quand on sait, avant de commencer, sur quoi on va boucler.
La variable i n'est pas la boucle : c'est une étiquette que Python décolle et recolle sur une nouvelle valeur à chaque tour, exactement comme au chapitre 2. Après la boucle, elle garde la dernière valeur prise.
On boucle aussi directement sur une suite de valeurs, sans passer par des numéros.
Les crochets créent une liste, une suite de valeurs rangées dans l'ordre. Le chapitre suivant lui est entièrement consacré ; ici, il suffit de savoir que for la parcourt du premier au dernier élément.
range(), et sa borne qui surprend
range(debut, fin, pas) engendre des entiers : debut inclus, fin exclue, pas valant 1 par défaut.
range(1, 10) ne contient pas 10. C'est déroutant au début, et parfaitement régulier : le nombre de valeurs vaut exactement fin - debut, ce qui évite une addition mentale à chaque usage.Pour aller jusqu'à 10 inclus, il faut écrire
range(1, 11). Enveloppe un range dans list() quand on doute : on verra les valeurs.
L'accumulateur est le motif le plus employé de toute la programmation, et le plus difficile à voir pour qui débute : la variable total change à chaque tour, et rien sur la page ne le montre. La figure ci-dessous le déroule.
| 1 | total = 0 |
| 2 | for n in [3, 7, 2]: |
| 3 | total = total + n |
| 4 | print(total) |
Variables
| total | 0 |
Trois choses se lisent sur cette trace, et aucune ne se déduit du code seul.
total = 0 s'exécute une seule fois, avant la boucle. Le placer à l'intérieur remettrait le compteur à zéro à chaque tour, et c'est l'erreur la plus fréquente sur ce motif.
La ligne for revient à chaque tour : c'est elle qui donne à n sa valeur suivante. La boucle n'est pas un bloc qu'on exécute trois fois d'affilée, c'est un aller-retour entre l'en-tête et le corps.
Enfin, n existe encore après la boucle et vaut 2, la dernière valeur prise. Python ne l'efface pas en sortant.
Répéter tant qu'une condition tient : while
La boucle while répète un bloc tant que sa condition est vraie. On l'emploie quand on ne sait pas d'avance combien de tours seront nécessaires.
Oui, une liste, un nombre de tours, un fichier : c'est un
for.Non, cela dépend de ce qui se passera pendant : c'est un
while. Attendre une saisie correcte, jouer jusqu'à ce qu'un joueur gagne, lire jusqu'à la fin d'un flux.Les débutants écrivent souvent un
while avec un compteur qu'ils incrémentent à la main, là où un for tenait en une ligne. Si on écrit compteur += 1 à la fin du while, demandons-nous si un for ne ferait pas l'affaire.
Un while a besoin de trois choses, et en oublier une est l'erreur classique : initialiser la variable avant, la tester dans la condition, et la faire évoluer dans le bloc.
Le bloc suivant est faux exprès : la troisième manque.
Rien ne fait grandir compteur, la condition reste vraie pour toujours. Au bout de quelques secondes, la plateforme interrompt l'exécution et affiche un message de dépassement de temps. Sur la machine, il faudrait interrompre le programme à la main.
À faire. Ajoute compteur += 1 dans le bloc et relance.
Le while demande une vigilance que le for n'exige pas : c'est au programmeur de faire progresser la condition vers sa fin. Dérouler la trace montre exactement ce qui rapproche du terme.
| 1 | n = 5 |
| 2 | resultat = 1 |
| 3 | while n > 1: |
| 4 | resultat = resultat * n |
| 5 | n = n - 1 |
| 6 | print(resultat) |
Variables
| n | 5 |
La ligne while est réévaluée à chaque tour, y compris la dernière fois où elle est fausse et fait sortir. La ligne n = n - 1 est la seule qui rapproche de cette sortie : la retirer donnerait une boucle sans fin, et le programme ne s'arrêterait jamais de lui-même.
break et continue
| Instruction | Effet |
|---|---|
break | sort de la boucle immédiatement |
continue | passe au tour suivant sans finir celui-ci |
Boucles imbriquées
Une boucle peut en contenir une autre. La boucle intérieure se déroule entièrement à chaque tour de la boucle extérieure.
Trois tours extérieurs, deux tours intérieurs à chaque fois : six lignes. C'est le schéma qui sert à parcourir un tableau à deux dimensions.
1.Que produit range(1, 5) ?
2.Avec note = 15, combien de lignes affiche une suite de trois if indépendants dont les conditions sont >= 10, >= 14 et >= 16 ?
3.if choix == 1 or 2: avec choix = 9. Que se passe-t-il ?
4.Quand faut-il un while plutôt qu'un for ?
5.Que vaut i juste après for i in range(3): pass ?
À mettre en pratique
FizzBuzz. Affiche les nombres de 1 à 20. Pour les multiples de 3, affiche Fizz ; pour les multiples de 5, Buzz ; pour les multiples de 3 et de 5, FizzBuzz.
Afficher la solution
L'ordre est ce qui compte. Le cas « multiple de 3 et de 5 » vient en premier : mis en dernier, il ne serait jamais atteint, puisqu'un multiple de 15 est déjà un multiple de 3 et sortirait sur le premier elif.
C'est exactement le piège de la section sur elif : avec une suite d'elif, le premier vrai gagne, donc le cas le plus restrictif se place en tête.
Synthèse
- L'indentation définit les blocs. Ce qui est décalé appartient au
ifou à la boucle. if/elif/elsesont testés dans l'ordre, et Python s'arrête au premier vrai.- Une suite de
ifévalue tout : ce n'est pas la même chose qu'unelif, et cela ne provoque aucune erreur. =colle une étiquette,==compare. Dans unif, on compare.if x == 1 or 2est toujours vrai : répéter la variable, ou employerin.forquand on sait sur quoi on boucle,whilequand on ne sait pas combien de tours.- Dans
range(a, b), la borne de fin est exclue. - Un
whilea besoin d'initialiser, tester, faire évoluer. Oublier le troisième donne une boucle infinie.
Mettre en pratique
if, elif, else et opérateurs de comparaison.
- Suivre une mention1 · Débuter
- Suivre un aiguillage1 · Débuter
- Accès réservé aux majeurs2 · Fonctions
- Numéro pair ou impair2 · Fonctions
- Le signe d'une mesure2 · Fonctions
- Valeur absolue d'un écart2 · Fonctions
- La plus grande de deux mesures2 · Fonctions
- Seuil d'alerte2 · Fonctions
- Attribuer une mention3 · Confirmé
- Attribuer une mention (autonome)3 · Confirmé
- Borner une tension (clamp)3 · Confirmé
- Trois longueurs forment-elles un triangle ?3 · Confirmé
- Débogage : le portail réservé aux majeurs2 · Fonctions
- Un mot de passe assez long1 · Débuter
- Une année bissextile1 · Débuter
for, while, accumulation et compteurs.
- Suivre une accumulation1 · Débuter
- Suivre une boucle while2 · Fonctions
- Cumul de production2 · Fonctions
- Compte à rebours2 · Fonctions
- Somme des nombres pairs2 · Fonctions
- Produit cumulé2 · Fonctions
- Puissance avec une boucle2 · Fonctions
- Compter les voyelles3 · Confirmé
- Somme de contrôle (chiffres)3 · Confirmé
- Afficher une table de multiplication1 · Débuter
- Débogage : le cumul oublie un jour2 · Fonctions
- S'arrêter au bon moment1 · Débuter
- Dessiner un triangle1 · Débuter