3. Structures conditionnelles

Jusqu’ici, notre programme s’exécutait une ligne après l’autre, de façon séquentielle, et toujours dans le même ordre et de la même façon. Nous allons maintenant voir comment permettre au programme d’exécuter certaines lignes plutôt que d’autres en fonction du contexte.

Objectifs de cette session :

  • comparer deux valeurs et obtenir une expression booléenne,

  • exécuter un bloc seulement si une condition est vraie, avec if,

  • comprendre le rôle de l’indentation,

  • choisir entre deux branches avec else, puis entre plusieurs avec elif,

  • combiner des conditions avec and, or et not,

  • tester la parité et la divisibilité avec %.

3.1. Comparer

Voici les opérateurs de comparaison que nous avons vus au §1.4.

Opérateur

Sens

Exemple

Résultat

<

strictement inférieur à

3 < 7

True

<=

inférieur ou égal à

7 <= 7

True

>

strictement supérieur à

3 > 7

False

>=

supérieur ou égal à

3 >= 7

False

==

égal à

7 == 7

True

!=

différent de

7 != 7

False

Leur résultat est toujours un bool. Toute expression qui produit True ou False s’appelle une expression booléenne.

Comme n’importe quelle valeur, le résultat d’une comparaison peut être affecté à une variable.

== et != fonctionnent aussi entre deux chaines. Elles sont alors comparées caractère par caractère : deux chaines ne sont égales que si elles sont rigoureusement identiques.

Avertissement

= affecte une valeur, == compare deux valeurs (§1.2). x = 5 modifie x ; x == 5 ne modifie rien : c’est une question, dont la réponse est True ou False.

Question

Laquelle de ces lignes est une expression booléenne ?

Exercice 1

Sans exécuter le code, prédisez les quatre valeurs affichées, puis vérifiez.

Solution

True : 12 est plus grand que 5.

False : 2 * b vaut 10, et 12 n’est pas inférieur ou égal à 10.

True : a - b vaut 7. Le calcul est fait avant la comparaison.

False : b + 7 vaut 12, donc a et b + 7 ne sont pas différents.

Exercice 2

Que se passe-t-il si vous échangez les deux côtés de x == 5 ? Et ceux de x = 5 ? Essayez les deux, lancez, lisez le message.

Solution

5 == x donne le même résultat que x == 5 : une comparaison est symétrique.

5 = x provoque SyntaxError: can't assign to literal, c’est-à-dire « impossible d’affecter une valeur à un littéral ». On ne peut affecter une valeur qu’à une variable : le nom doit être à gauche du =.

3.2. L’instruction if

Jusqu’ici, toutes les lignes d’un programme s’exécutaient, les unes après les autres. L’instruction if (si) permet de n’exécuter certaines lignes que si une expression booléenne vaut True. Placée après if, cette expression s’appelle la condition.

if condition:
    instruction
    instruction
suite du programme

La ligne if se termine par deux-points. Les lignes qui suivent, décalées de quatre espaces, forment un bloc : elles ne s’exécutent que si la condition est vraie. Ce décalage s’appelle l’indentation.

En Python, l’indentation n’est pas une décoration : c’est elle qui indique où le bloc commence et où il s’arrête. La première ligne qui revient à gauche ne fait plus partie du bloc, et s’exécute dans tous les cas.

Remplacez 31 par 25 et relancez : seule la dernière ligne s’affiche.

La condition peut être n’importe quelle expression booléenne : une comparaison, une variable de type bool, et même True ou False écrit directement.

Note

Les éditeurs comme Thonny indentent automatiquement la ligne qui suit un deux-points. Pour revenir à gauche, effacez l’indentation avec la touche de retour arrière.

Question

Dans la ligne if total > 100:, quelle est la condition ?

Exercice 3

Sans exécuter le code, prédisez ce qu’il affiche. Faites de même en remplaçant 7 par 12, puis par 3. Vérifiez.

Solution

Avec 7 : A, C, D. Le premier bloc s’exécute et fait passer points à 2. La deuxième condition est alors fausse. C s’affiche toujours, et points == 2 est vrai.

Avec 12 : A, B, C. Après le premier bloc, points vaut 7, qui est encore plus grand que 5.

Avec 3 : seulement C.

Chaque if est évalué avec la valeur de points au moment où on l’atteint, pas avec sa valeur de départ.

Exercice 4

Ce programme contient une erreur. Lancez-le, lisez le message, puis corrigez.

Solution

SyntaxError: bad input on line 3, c’est-à-dire « entrée incorrecte à la ligne 3 » : Python n’a pas pu lire la ligne 3, car après le if de la ligne 2 il attendait une ligne indentée. Un if doit toujours être suivi d’au moins une ligne indentée.

Dans Thonny, le message est plus précis : IndentationError: expected an indented block after 'if' statement on line 2, « un bloc indenté était attendu après l’instruction if de la ligne 2 ».

3.3. if … else

else (sinon) introduit un second bloc, exécuté quand la condition est fausse. Des deux blocs, exactement un s’exécute : jamais les deux, jamais aucun.

if condition:
    bloc exécuté si la condition est vraie
else:
    bloc exécuté si la condition est fausse

else n’a pas de condition. Il est suivi de deux-points et aligné sur son if. Chacun de ces chemins possibles s’appelle une branche.

Pour vérifier un programme qui contient une condition, il faut le tester avec la valeur exacte du seuil, et avec une valeur de chaque côté. Ici : -1, 0 et 1. C’est en général au seuil que se cache l’erreur, par exemple un > écrit à la place d’un >=.

Question

Dans une structure if … else, combien de blocs sont exécutés ?

Exercice 5

Un ascenseur supporte au maximum 630 kg. Complétez le programme pour qu’il affiche Départ si la masse le permet, et Surcharge sinon. Testez-le au seuil.

Solution

Exercice 6

Ce programme fonctionne, mais il peut être simplifié. Réécrivez-le avec else.

Solution

Avec deux if, il faut écrire soi-même la condition contraire, et le risque est de se tromper : avec n > 100 à la place de n >= 100, la valeur 100 n’afficherait rien.

Exercice 7

Voici une autre version à deux if. Lancez-la en tapant 100. Que se passe-t-il ? Réécrivez-la avec else.

Solution

Le programme affiche Grand puis Petit. Les deux if sont indépendants : chacun est testé, et 100 vérifie les deux conditions à la fois.

Avec else, on n’a plus à vérifier que les deux conditions ne se chevauchent pas, ni qu’elles couvrent tous les cas : exactement un bloc est exécuté, quelle que soit la valeur.

3.4. elif, un if dans un else

Avec trois cas, un seul if … else ne suffit plus. On peut placer un second if dans le bloc else du premier : il n’est testé que si la première condition est fausse.

Cette imbrication est si fréquente que Python la raccourcit : else: suivi d’un if s’écrit elif, contraction de else if. Le programme suivant est exactement équivalent au précédent.

Les conditions sont testées dans l’ordre. La première qui vaut True fait exécuter son bloc, et toutes les suivantes sont ignorées. Le else final, facultatif, récupère tous les cas restants. On peut enchainer autant de elif que nécessaire sans que l’indentation ne s’accumule.

Faut-il une chaine if … elif ou plusieurs if séparés ? Tout dépend des cas. S’ils s’excluent (une eau ne peut pas être à la fois glace et vapeur), on veut une seule branche : elif. S’ils peuvent se cumuler, chacun a besoin de son propre if, comme à l’exercice 3.

Question

Avec temperature = 0, qu’affiche le programme ci-dessus ?

Exercice 8

Lancez ce programme avec l’âge 70. Pourquoi le tarif senior n’apparait-il jamais ? Corrigez.

Solution

Toute personne de 65 ans ou plus a aussi 16 ans ou plus : la première condition est vraie, et les suivantes ne sont même pas testées. Il faut tester le cas le plus restrictif en premier.

Exercice 9

Remplacez chaque True par une condition, pour que le programme respecte les commentaires.

Solution

3.5. and, or et not

Les opérateurs logiques combinent des expressions booléennes :

  • a and b est vrai si a et b sont vrais tous les deux,

  • a or b est vrai si au moins un des deux est vrai,

  • not a est vrai si a est faux, et inversement.

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

Attention au sens de ou. En français, le ou est souvent inclusif, mais parfois exclusif. Par exemple, si on vous demande si vous avez un frère ou une soeur, vous répondrez oui si vous avez l'un des deux, mais également si vous avez les deux : c'est donc un ou inclusif. Par contre, si on vous indique qu'un menu inclut "fromage ou dessert", il est entendu que vous ne pouvez pas prendre les deux : c'est donc un ou exclusif. Le or de Python est toujours inclusif, et l'ensemble est donc vrai aussi quand les deux côtés sont vrais.

Pour vérifier qu’une valeur se trouve entre deux bornes, il faut deux comparaisons reliées par and.

Les parenthèses autour de chaque comparaison ne sont pas indispensables, mais nous les écrirons toujours : elles montrent ce qui est comparé avant d’être combiné.

Quand on mélange and et or dans une même expression, elles deviennent obligatoires : selon leur place, le résultat change.

Note

not s’applique uniquement à ce qui le suit immédiatement : not a and b se lit (not a) and b. Pour inverser toute une expression, on l’entoure de parenthèses : not (a and b).

Question

Que vaut (5 > 3) or (2 > 4) ?

Question

Pour que a and b vaille False, il suffit que

Exercice 10

Pour monter dans un grand huit, il faut mesurer entre 120 et 195 cm, bornes comprises. Demandez la taille, puis affichez Accès autorisé ou Accès refusé.

Solution

Exercice 11

Reprenez l’exercice précédent en inversant l’ordre des branches : le premier bloc affiche Accès refusé. Remplacez True par la condition, écrite de deux façons : d’abord avec not, puis sans.

Solution

3.6. Le reste %

L’opérateur % a été vu aux §1.4 et §2.7. a % b est ce qui reste de a quand on en a retiré autant de fois b que possible. 17 % 5 vaut 2, car 17 = 3 × 5 + 2 : le quotient 17 // 5 vaut 3, le reste vaut 2.

Le reste est toujours compris entre 0 et b - 1. Il vaut 0 exactement quand la division tombe juste. D’où une traduction directe : « n est divisible par d » s’écrit n % d == 0.

Cas particulier : un nombre est pair s’il est divisible par 2, donc si n % 2 == 0. Sinon il est impair, et n % 2 vaut 1.

Question

Que vaut 24 % 6 ?

Question

Quelle condition teste si n est un multiple de 7 ?

Exercice 12

Des œufs sont vendus par boites de 6. Demandez un nombre d’œufs. Affichez si toutes les boites sont pleines, ou sinon combien d’œufs contient la dernière boite.

Solution

Exercice 13

Demandez un entier. Affichez Fizz s’il est multiple de 3, Buzz s’il est multiple de 5, FizzBuzz s’il est multiple des deux, et le nombre lui-même sinon. Testez avec 9, 10, 15 et 7.

Solution

Au chapitre 5, une boucle permettra d’appliquer ce programme à tous les nombres de 1 à 100.

3.7. Erreurs fréquentes

Le tableau des types d’erreur du §2.8 s’enrichit d’une ligne.

Type

Sens

Message typique

SyntaxError

Python n’arrive pas à lire le code

'(' was never closed

NameError

un nom est utilisé sans avoir reçu de valeur

name 'z' is not defined

TypeError

un opérateur reçoit des opérandes de types incompatibles

can only concatenate str (not "int") to str

ValueError

le type est bon, mais la valeur est inexploitable

invalid literal for int() with base 10

ZeroDivisionError

division par zéro

division by zero

IndentationError

l’indentation ne correspond pas à la structure du code

expected an indented block after 'if' statement

Une IndentationError est une forme particulière de SyntaxError : Python n’arrive pas à lire le fichier, et rien ne s’exécute.

Note

L’éditeur de cette page et Thonny n’affichent pas toujours le même message. Le type d’erreur et le numéro de ligne sont les mêmes, mais la phrase de Thonny est souvent plus précise. Une exception : dans cette page, une erreur d’indentation est signalée comme SyntaxError: bad input, et non comme une IndentationError.

Quelques mots s’ajoutent au vocabulaire des messages :

Mot anglais

Ce que ça veut dire

bad input

entrée incorrecte : Python n’a pas pu lire cette ligne ; regardez-la, et la précédente

expected

attendu : Python s’attendait à trouver quelque chose à cet endroit

indented block

bloc indenté

statement

instruction, par exemple l’instruction if

can't assign

impossible d’affecter une valeur

not supported between instances of

impossible entre des valeurs de type…, par exemple '<' not supported between instances of 'str' and 'int'

Exercice 14

Corrigez les deux erreurs. Python s’arrête à la première : il faudra relancer.

Solution

Premier lancement : SyntaxError: bad input on line 2. Une condition compare : il faut ==.

Second lancement : SyntaxError: bad input on line 4. Il manque le deux-points en fin de ligne.

bad input ne dit pas ce qui manque : c’est le numéro de ligne qui guide la recherche.

Exercice 15

Ce programme s’exécute sans erreur, mais un adulte paie demi-tarif. Pourquoi ? Corrigez.

Solution

La ligne prix = prix // 2 n’est pas indentée : elle ne fait pas partie du bloc, et s’exécute donc pour tout le monde. Python ne peut pas deviner l’intention : seule l’indentation compte.

Exercice 16

Ce programme accepte n’importe quel choix, même 3. Pourquoi ? Corrigez.

Solution

or relie deux expressions : choix == 1 d’un côté, et 2 tout seul de l’autre. Converti en booléen, 2 vaut True (§2.5), donc la condition est toujours vraie. Chaque côté de or doit être une comparaison complète.

3.8. Exercices

Ces trois programmes réinvestissent tout le chapitre. Écrivez-les dans un éditeur externe (Thonny), puis déposez vos fichiers sur Moodle.

Exercice 17 — 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. Demandez une année et affichez si elle est bissextile.

Testez au moins 2024, 2026, 1900 et 2000.

Exercice 18 — Calculatrice

Demandez deux entiers, puis un opérateur parmi +, -, *, // et %. Affichez le résultat de l’opération.

Si l’opérateur n’est pas dans la liste, affichez Opérateur inconnu. Si l’opération est une division par zéro, affichez un message à la place du calcul : le programme ne doit jamais s’arrêter sur une erreur.

Exercice 19 — Billet de cinéma

Un cinéma applique les tarifs suivants :

  • moins de 6 ans : gratuit,

  • de 6 à 15 ans : 10 CHF,

  • 16 ans et plus : 16 CHF, ou 12 CHF pour les étudiants de 25 ans au plus,

  • le mercredi, tous les billets payants coutent 3 CHF de moins.

Demandez l’âge, si la personne est étudiante (oui ou non) et le jour de la semaine, puis affichez le prix du billet.

3.9. Résumé

  • une comparaison produit un bool : c’est une expression booléenne ; entre chaines, == exige une égalité caractère par caractère,

  • if condition: exécute le bloc qui suit seulement si la condition vaut True,

  • l’indentation délimite le bloc ; la première ligne revenue à gauche s’exécute dans tous les cas,

  • else ouvre une seconde branche ; elif est un if dans un else : la première condition vraie l’emporte, et l’ordre compte,

  • and, or et not combinent des conditions ; dès qu’on mélange and et or, on met des parenthèses,

  • n % d == 0 signifie « n est divisible par d » ; n % 2 donne la parité.