11 - Conditions
Nous abordons aujourd'hui une autre notion très importante pour réaliser des choses intéressantes : les instructions conditionnelles.
En une question : comment réaliser des choses différentes en fonction de la situation ?
Evaluation ✎ : questions 08-14-16-18-19
1 - Booléens
Booléens
Pour comprendre les tests logiques, il faut savoir que les ordinateurs n'ont que deux choix possibles lorsqu'on leur donne une proposition à tester (du style "est-on en 2025 ?"). Il s'agit d'un booléen, d'après George Boole, fondateur de l'algèbre de Boole dans le milieu du 19ème siècle.
Un booléen ne peut valoir que True (pour VRAI) ou False (pour FAUX). Dans les faits, Python considère que 0 correspond à False et le reste à True.
- Si nous étions en 2025, le résultat de "Sommes-nous en 2025 ?" donnerait True.
- Sinon, le résultat donnerait False.
D'un point de vue informatique, cela donne :
>>> annee = 2025
>>> annee == 2025
True
>>> annee != 2025
False
>>> annee > 2025
False
>>> annee >= 2025
True
>>> annee < 2025
False
>>> annee <= 2025
True
01° Utiliser ces instructions dans la console pour comprendre le principe de l'évaluation du booléen obtenu.
>>> a = 12
>>> b = 20
>>> b > a
True
>>> b < a
False
>>> b == a
False
>>> b != a
True
On peut même stocker une évaluation dans une variable.
02° Trouver le contenu stocké dans les différentes variables c, d, e et f.
Après avoir obtenu vos réponses, vérifier à l'aide de la console.
>>> a = 12
>>> b = 20
>>> c = b > a
>>> d = b < a
>>> e = b == a
>>> f = b != a
...CORRECTION...
>>> a = 12
>>> b = 20
>>> c = b > a
>>> c
True
>>> d = b < a
>>> d
False
>>> e = b == a
>>> e
False
>>> f = b != a
>>> f
True
Nous allons pouvoir utiliser ces booléens pour réaliser des instructions conditionnelles : des instructions qui vont être réalisées uniquement si la condition est évaluée à VRAI.
2 - Instruction conditionnelle SI
Structure générale des instructions conditionnelles
Quelque soit le langage, on retrouve toujours une structure qui ressemble à ceci :
1
2
3
4
5
6
7
8
9
10
11 |
|
03° Tester la fonction suivante en lui fournisant diiférents paramètres entre 1980 et 2010 par exemple.
1
2
3
4
5
6
7
8
9
10 |
|
>>> creer_message(2000)
???
Questions :
- La fonction renvoie-t-elle systématiquement la même réponse pour par exemple 1980, 1991 et 2050 ?
- Ligne 4 : comment est évaluée l'expression
reponse > annee_creation_python
si le paramètre reponse contient1987
? Du coup, va-t-on exécuter la ligne 5 ? - Ligne 6 : comment est évaluée l'expression
reponse < annee_creation_python
si le paramètre reponse contient1987
? Va-t-on exécuter la ligne 7 ? - Avec quel mot-clé se code le SI en Python ?
- Avec quel mot-clé se code le SINON SI en Python ?
- Avec quel mot-clé se code le SINON en Python ?
...CORRECTION...
On constate bien que la fonction renvoie des réponses différentes en fonction de la valeur que reçoit la fonction en entrée :
>>> creer_message(2000)
'Python a été créé avant 2000'
>>> creer_message(1980)
'Python a été créé après 1980'
>>> creer_message(1991)
'Oui, Python est sorti pour la première fois en 1991'
L'expression reponse > annee_creation_python
est évaluée progressivement de cette façon :
reponse > annee_creation_python
1987 > annee_creation_python
1987 > 1991
False
On n'exécute donc pas la ligne 5 de ce bloc.
L'expression reponse < annee_creation_python
est évaluée progressivement de cette façon :
reponse < annee_creation_python
1987 < annee_creation_python
1987 < 1991
True
Du coup, on va exécuter la ligne 7 qui appartient à ce bloc.
Le SI se code avec le mot-clé if.
Le SINON SI se code avec le mot-clé elif.
Le SINON (tout court) se code avec le mot-clé else.
04° Que trouve-t-on à la fin de chacune des lignes contenant if, elif ou else ?
Comment sont positionnées les instructions conditionnelles par rapport aux mots-clés précédents ?
A quelle autre syntaxe cela vous fait-il penser ?
...CORRECTION...
On retrouve la structure d'une fonction.
On finit chaque condition par :
.
On tabule chaque instruction liée à une condition.
C'est l'indentation vers la droite qui permet à Python de comprendre les actions que vous voulez qu'il réalise si une condition est vérifiée. Il faut donc placer une tabulation ou 4 espaces de suite pour savoir qu’elles sont les instructions rattachées au bloc. De plus, on remarquera qu’on met un double point [ : ] après la condition de if, else if (elif en Python) ou else. Sans ce symbole, vous déclenchez une erreur. Ce double point permet de dire à l'interpréteur que la déclaration de la condition est finie.
Dans Thonny ou tout autre éditeur spécialisé dans Python, la tabulation est équivalente à 4 espaces. Attention par contre aux éditeurs multi-langages. La tabulation est parfois de 2 ou 3 espaces. Dans ce cas, votre code ne sera pas compris par l'interpréteur Python. Dans ce cas de figure, préférez les 4 espaces ou configurez votre éditeur pour forcer une tabulation équivalente à 4 espaces.
05° Utiliser l'animation ci-dessous en utilisant les trois paramètres qu'on demande à la fonction de traiter.
Question :
Que fait l'interpréteur à partir du moment où il valide l'une des conditions à évaluer ?
1
2
3
4
5
6
7
8
9
10 |
|
CLIQUEZ SUR UN BOUTON-REPONSE :
reponse :
annee_creation :
condition :
...CORRECTION...
L'interpréteur ne traitera que l'un des blocs.
Dès qu'il rencontre une condition valide, il exécute les instructions correspondantes puis quitte la structure conditionnelle SANS tester les possibilités restantes.
Déroulement d'une séquence if-elif-else
A SAVOIR IMPERATIVEMENT
L'interpréteur Python ne va exécuter que l'un des blocs d'une structure if-elif-else.
Python commence par évaluer la condition du premier bloc.
Si la condtion est vraie, il exécute les instructions 2-3-4 de ce bloc et ne regardera absolument pas les autres conditions et blocs. Il passera directement à la ligne Instruction 9
.
Instruction 1 (avant les instructions conditionnelles)
if reponse > annee_creation_python :
Instruction 2
Instruction 3
Instruction 4
elif reponse < annee_creation_python :
Instruction 5
Instruction 6
Instruction 7
else :
Instruction 8
Instruction 9
Instruction 10 (après les instructions conditionnelles)
Si la première condtion est fausse, il va évaluer la deuxième condition. Si elle est vraie, il exécute les instructions 5-6-7 de ce bloc et ne regardera absolument pas le dernier bloc. Il passera directement à la ligne Instruction 9
.
Si aucune des conditions précédentes n'est vraie, il va sinon réaliser les instructions 8-9 du dernier bloc. Le ELSE est donc le bloc par défaut. Celui qu'on exécute si aucune des conditions précédentes n'a pas être validée.
Je répète : La chose à bien comprendre : l'interpréteur Python ne va exécuter que l'un des blocs. Il s'arrête au premier test correct et ne s'occupe pas des autres situés en dessous, même si les conditions sont vraies également.
06° Compléter la fonction appreciation ci-dessous. Elle doit renvoyer "Bien" si le paramètre note est supérieur à 13, "Insuffisant" si le paramètre est inférieur à 9 et "Moyen" sinon.
1
2
3
4
5
6
7
8 |
|
...CORRECTION...
Version un seul endroit où on gère l'envoi de la réponse.
1
2
3
4
5
6
7
8
9
10
11
12
13
14 |
|
07° Quelqu'un propose cette version 02 (elle est valide) permettant de répondre dès qu'on sait quoi répondre plutôt que de traiter les différents cas et d'envoyer la réponse à la fin.
1
2
3
4
5
6
7
8
9
10
11
12
13 |
|
Une autre personne pense qu'on peut encore faire plus rapide en supprimant le else final avec cette version 03 (elle est valide également).
1
2
3
4
5
6
7
8
9
10
11
12 |
|
Un enthousiaste pense du coup à modifier la première version est propose une version 04 (version fausse cette fois).
1
2
3
4
5
6
7
8
9
10
11
12
13 |
|
Question
Expliquez pourquoi on peut se passer du else dans la version 3 mais pas dans la version 4.
...CORRECTION...
La version 03 fonctionne car dès qu'on rencontre un return, on répond et on sort de la fonction.
Si on atteint les lignes 9 ou 11, on quitte donc la fonction. Cela veut dire qu'on ne peut arriver à la ligne 12 que si la note n'est ni supérieure à 13, ni inférieure à 9.
Par contre, dans la version 04, il ne place pas de return. Cela veut dire que même si on rentre dans l'un des blocs if ou elif, on affectera la variable app mais on ne sortira pas de la fonction.
Du coup, on va simplement atterir ligne 12 à chaque fois et écraser la version précédente de notre variable !
Ici, le else est donc obligatoire.
✎ 08° Compléter la fonction traduction ci-dessous. Elle doit renvoyer "vert" si le paramètre color est "green", "rouge" pour "red", "bleu" pour "blue", "jaune" pour "yellow". Si la couleur est inconnue, elle doit répondre "Couleur non définie".
Remarque : nous verrons plus tard dans l'année un moyen plus efficace de traiter ceci que comme une succession de tests.
1
2
3
4
5
6
7
8
9 |
|
3 - Fonction booléenne
Nous avons déjà vu le test d'égalité. C'est à dire tester si une variable contient bien 5 par exemple.
Pour tester une égalité en Python, on n'utilise pas a = b
qui donne un ordre d'affectation : l'ordinateur comprend dans ce cas qu'il faut stocker b dans la variable a.
Tester une égalité avec Python
Pour tester l'égalité, on utilise un double signe égal a == b
. Cette instruction teste réellement si les deux variables sont égales.
Fonction boolèenne
C'est simplement une fonction qui renvoit un booléen.
True ou False en Python.
09° Compléter la fonction comparer pour qu'elle renvoie True si les deux paramètres sont égaux.
1
2
3 |
|
...CORRECTION...
Il est probable que vous avez tapé quelque chose qui ressemble à cela :
1
2
3
4
5
6 |
|
Si vous avez mémorisé l'histoire du return qui provoque une sortie de la fonction, vous avez même surement tapé ceci :
1
2
3
4
5 |
|
Et pourtant, il a eu encore une manière plus courte de répondre (les explications sont ci-dessous si vous ne comprennez pas bien comment ça fonctionne) :
1
2
3 |
|
Ce cas de figure est très courant en informatique : créer une fonction booléenne (une fonction qui renvoie True ou True) ne requiert donc pas d'utiliser un if la plupart du temps : il suffit de renvoyer l'expression qu'on veut évaluer.
Exemple avec une expression qui évalue si une note de 10 permet de valider un semestre :
>>> note = 9
>>> note >= 10
False
>>> note = 12
>>> note >= 10
True
Du coup, la fonction donnerait simplement ceci :
1
2
3 |
|
10° Evaluer note >= 10
si le paramètre note vaut 7. Que va renvoyer la fonction valider ?
...CORRECTION...
note >= 10
7 >= 10
11° Un élève propose cette version : est-elle bonne, fausse, correcte mais inutilement longue ?
1
2
3
4
5
6 |
|
...CORRECTION...
Bonne mais inutilement longue.
Si vous préférez cette version pendant quelques temps, utilisez la. Vous aurez les points.
Mais dès que vous serez à l'aise, passez plutôt à la version courte.
4 - Inversion d'un booléen avec not
Nous allons voir comment utiliser ces fonctions booléennes de manière élégante.
Tester une évaluation sur VRAI
Globalement, si on veut faire des choses si cette fonction renvoie True, il suffit de faire ceci :
1
2
3
4 |
|
Cela revient à réaliser si l'expression est évaluée à True. Nous aurions pu écrire ceci (mais c'est plus long)
1
2
3
4 |
|
Imaginons qu'on veuille tester si une moyenne est bien validée avec la fonction valider.
1
2
3 |
|
Il suffit de taper ceci :
Ok et élégant |
|
Par défaut, Python évalue la condition et valide si la réponse est True. Mais comme ici nous obtenons directement un booléen, pas la peine d'en rajouter.
C'est comme si nous avions tapé ceci :
Ok mais bof bof |
|
Tester une évaluation sur FAUX
Par contre, si on veut agir lorsque cette fonction renvoie False, on peut donc faire :
1
2
3
4 |
|
Et bien, on peut faire plus simple et plus clair en utilisant le mot-clé not : ce mot-clé inverse la valeur du booléen situé derrière lui.
>>> condition = False
>>> condition
False
>>> not condition
True
Du coup, on peut écrire plus proprement le fait d'agir si la fonction comparer renvoie False.
1
2
3
4 |
|
Imaginons qu'on veuille tester si une moyenne n'est pas validée avec la fonction valider.
Par défaut, Python évalue la condition et valide si la réponse est True. Comme la fonction renvoie un booléen, nous pourrions faire ceci :
Ok mais bof bof |
|
Mais en fait, il suffit d'inverser la réponse de la fonction avec not
Ok et élégant |
|
12° Quelle va être l'instruction réalisée si comparer renvoie False.
1
2
3
4 |
|
...CORRECTION...
not comparer(choix, m)
not False
True
Comme la condition de la ligne 1 donne True, on effectue la fonction tache_1.
5 - ET / OU
Imaginons qu'on veuille créer une fonction est_valide qui vérifie qu'une note est bien comprise entre entre 0 et 20.
1
2
3
4
5
6
7
8
9
10
11
12 | def est_valide(n):
'''Fonction qui renvoie True si n est un entier dans [0;20]
:: param n(int) :: un entier quelconque
:: return (bool) :: True si n est dans [0;20], False sinon
'''
if n > 20 :
return False
elif n < 0 :
return False
return True
|
13° Expliquer pourquoi la fonction est_valide ne renvoie pas systématiquement True alors qu'il s'agit de la dernière ligne de cette fonction.
...CORRECTION...
Tout simplement car on sort de la fonction dès qu'on rencontre un return.
Si l'un des deux tests précédents renvoie True, on va donc exécuter le return False
et sortir de la fonction.
✎ 14° Un élève propose la fonction ci-dessous. Expliquer clairement pourquoi sa fonction n'est pas correcte alors qu'elle ne déclenche pas d'erreur et qu'elle renvoie bien True pour une note de 15 par exemple.
1
2
3
4
5
6
7
8
9
10
11
12 | def est_valide(n):
'''Fonction qui renvoie True si n est un entier dans [0;20]
:: param n(int) :: un entier quelconque
:: return (bool) :: True si n est dans [0;20], False sinon
'''
if n <= 20 :
return True
elif n >= 0 :
return True
return False
|
Si vous ne trouvez pas, demandez-vous ce qu'elle renvoie pour une note de -15.
Pour obtenir un code plus lisible et concis, il existe un moyen d'associer la réponse de plusieurs tests logiques.
Voyons comment cela fonctionne.
15° Tapez les instructions ci-dessous dans le Shell.
>>> note = 15
>>> note >= 0
True
>>> note < 0
False
>>> note <=20
True
>>> note > 20
False
>>> note >= 0 and note <= 20
True
>>> note = 25
>>> note >= 0 and note <= 20
False
Question : lorsque deux conditions sont reliées par un and, dans quel cas l'expression totale va-t-elle évaluée à True ?
...CORRECTION...
L'expression n'est évaluée à True qui si les deux conditions sont également évaluées à True. Il s'agit d'un ET logique.
Voici donc une manière plus simple de créer notre fonction est_valide. Cela ne change en rien son utilisation : pour l'utilisateur, le changement est totalement invisible.
1
2
3
4
5
6
7
8 | def est_valide(n):
'''Fonction qui renvoie True si n est un entier dans [0;20]
:: param n(int) :: un entier quelconque
:: return (bool) :: True si n est dans [0;20], False sinon
'''
return n >= 0 and n <= 20
|
Une seule ligne, hors documentation. Pas mal non ?
✎ 16° Un élève propose la fonction ci-dessous. Expliquer clairement pourquoi vous pensez que sa fonction est correcte ou fausse (pensez à regarder les préconditions sur le paramètre n).
1
2
3
4
5
6
7
8 | def est_valide(n):
'''Fonction qui renvoie True si n est un entier dans [0;20]
:: param n(int) :: un entier quelconque
:: return (bool) :: True si n est dans [0;20], False sinon
'''
return n > -1 and n < 21
|
Nous allons revoir en détail le ET dans d'autres activités. Voici simplement ce qu'on nomme la table de vérité d'un ET :
Valeur de a | Valeur de b | a ET b |
---|---|---|
VRAI | VRAI | VRAI |
FAUX | VRAI | FAUX |
VRAI | FAUX | FAUX |
FAUX | FAUX | FAUX |
Il existe également le OU
Un ET répond VRAI lorsque toutes les entrées sont VRAIES. Le OU répond VRAI lorsqu'une des entrées au moins est VRAIE. 17° Compléter la table de vérité du OU : Cela revient à chercher cela avec Python : ✎ 18° QCM : On demande à quatre élèves de créer une fonction note_invalide. Elle doit renvoyer True si la note n n'est pas dans [0;20]. On vous fournit ci-dessous la réponse de leur fonction. Quel élève fournit la bonne façon de repondre ?
Valeur de a
Valeur de b
a OU b
VRAI
VRAI
?
FAUX
VRAI
?
VRAI
FAUX
?
FAUX
FAUX
?
a or b
...CORRECTION...
Valeur de a
Valeur de b
a OU b
VRAI
VRAI
VRAI
FAUX
VRAI
VRAI
VRAI
FAUX
VRAI
FAUX
FAUX
FAUX
return n >= 0 or n <= 20
return n <= 0 or n >= 20
return n > 0 or n < 20
return n < 0 or n > 20
6 - Jeu, Hasard et Interface
Nous allons finir avec une petite application graphique Turtle qui permet de réaliser une animation : une balle rebondit sur les parois.
✎ 19° Mettre le programme en mémoire.
Activer en lançant la fonction lancer_animation dans la console. Cela vous permettra de voir l'animation réalisée pour l'instant.
>>> lancer_animation()
Analyse du code : Répondre aux questions suivantes :
- Sur quelle ligne définit-on que (sur cette application) les modifications sur les dessins ne seront pas automatiquement mises à jour à l'écran mais uniquement lorsqu'on en fait une demande d'update ?
- Sur quelle ligne donne-t-on la valeur en pixels du terrain de jeu ? On notera que si la valeur est 200, cela veut dire que les balles pourront évoluer en x (axe horizontal, abscisse) et en y (axe vertical, ordonnée) de -200 à +200.
- On crée alors les balles avec la fonction balle. A quoi sert la ligne 52 ?
- Combien de fois de suite va-t-on mettre les images en jour à l'aide d'une boucle ?
- Ligne 94 : on efface l'ancienne image qui avait été dessinée par le feutre
- Ligne 95 : on bouge le feutre à l'aide de la fonction bouger
- Ligne 96 : on dessine la nouvelle image
- Sur quelle ligne demande-t-on à l'application de faire cette mise à jour justement ?
Le principe de l'animation réalisée par la fonction deplacer_image est simple :
L'ancienne image est donc remplacée par la nouvelle.
Une fois qu'on a fait cela, il ne reste plus qu'à demander à l'application graphique d'afficher les modifications que nous venons de faire.
...CORRECTION...
- LIGNE 33 :
fenetre.tracer(0)
- LIGNE 101 :
dim = 200
- La ligne 52 (et sa vitesse 0) permet d'afficher sans délai le dessin : on ne laisse pas l'utilisateur voir la "tortue" dessiner le cercle. Il apparaît point.
- Ligne 110 : on voit que la boucle va être réalisée 8000 fois. Après, c'est fini. Ca ne bougera plus.
- Ligne 115 : c'est sur cette dernière ligne de la boucle FOR qu'on demande à l'application de mettre à jour l'affichage.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115 |
|
20° Compléter maintenant la fonction bouger ci-dessous. On remarquera notamment que j'ai changé la valeur du déplacement de façon à accélerer un peu les choses.
Pour l'instant, on ne gère que le contact avec le mur de droite. Vous pouvez tester. Ensuite, c'est à vous de parvenir à gèrer le mur de gauche (une paroi verticale), le sol et le plafond (deux parois horizontales).
N'oubliez pas d'activer l'animation !
>>> lancer_animation()
Voici la fonction à modifier et compléter.
1
2
3
4
5
6
7
8
9
10 |
|
...CORRECTION...
1
2
3
4
5
6
7
8
9
10
11
12 |
|
7 - FAQ
Du coup, on peut tester le type des variables ?
Oui. Les deux manières de faire les plus courantes sont fournies ci-dessous :
Première méthode : tester le type de la variable.
>>> a = 5.0
>>> type(a) == float
True
>>> type(a) == int
False
>>> type(a) == str
False
>>> a = "5.0"
>>> type(a) == float
False
>>> type(a) == int
False
>>> type(a) == str
True
Deuxième façon de faire : utiliser la fonction native isinstance.
>>> a = 5
>>> isinstance(a, float)
False
>>> isinstance(a, int)
True
>>> isinstance(a, str)
False
Activité publiée le 01 11 2020
Dernière modification : 01 11 2020
Auteur : ows. h.