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-20
Documents de cours : open document ou pdf
1 - Cours
Le cours n'est pas destiné à être lu d'un bloc. Vous pouvez passer si vous travaillez en autonomie : les bouts de cours à connaître sont fournis au fur et à mesure dans les activités.
1 - Booléens
Les ordinateurs n'ont que deux choix possibles lorsqu'on leur donne une proposition à tester (du style "Sommes-nous en 2025 ?"). La réponse est donc 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).
- Si nous étions en 2025, l'évaluation de l'expression "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
2 - Instruction ou expression ?
Une instruction va modifier l'état de la mémoire. L'affectation est l'instruction la plus fondamentale.
Une expression est un ensemble de valeurs et d'opérateurs pouvant être évaluée. L'évaluation d'une expression correspond à la recheche de sa valeur.
Si l'expression ne contient pas d'instruction, il n'y a pas de modification de l'état du programme.
Exemple d'affection utilisant une évaluation à droite :
>>> c = b > a
On peut dire que b > a est une expression (booléenne puisqu'elle va être évaluée à True ou False).
Par contre, c = b > a dans son ensemble est une instruction (une instruction d'affectation ici) puisqu'elle va modifier l'état de la variable c.
Exemple d'évaluation (la console affichant la valeur évaluée puisqu'on ne la redirige nulle part):
>>> "La" in 'Lalala'
True
Exemple d'instruction
>>> d = "La" in 'Lalala'
C'est bien une instruction puisque l'état de la mémoire est différent après application de cette instruction : on a créé ou modifié le contenu affecté à la variable d.
3 - Structure générale des instructions conditionnelles SI - SINON SI - SINON
Quelque soit le langage, on retrouve toujours une structure qui ressemble à ceci :
1
2
3
4
5
6
7
8
9
10
11 |
|
Nombre de blocs
- Un unique bloc SI et il doit toujours être en première position
- 0, 1 ou autant de blocs SINON SI que vous voulez (il peut ne pas y en avoir)
- 0 ou 1 bloc SINON et il doit toujours être en dernière position : c'est le bloc par défaut. Si aucun autre n'a été activé, on prend celui-ci.
4 - Déroulement d'une séquence if-elif-else en Python
A SAVOIR IMPERATIVEMENT
L'interpréteur Python n'exécute que l'un des blocs A, B ou C d'une structure if-elif-else.
Il exécute les instructions du bloc de la première expression évaluée à True puis quitte la structure même si les autres expressions sont vraies également.
Exemple
Instructions Avant 1
Instructions Avant 2
if note > 11: # BLOC A
Instruction A1
Instruction A2
Instruction A3
elif note < 9: # BLOC B
Instruction B1
Instruction B2
Instruction B3
else: # BLOC C
Instruction C1
Instruction C2
Instructions Après 1
Instructions Après 2
Déroulement
Bloc A if : SI l'expression A (note > 11) est évaluée à True, il exécute A1-A2-A3 puis atteint directement Après 1. Sinon, il passe au bloc B.
Bloc B elif : SINON, SI l'expression B (note < 9) est évaluée à True, il exécute B1-B2-B3 puis atteint directement Après 1. Sinon, il passe au bloc C.
Bloc C else : on réalise forcément les instructions C1-C2 si on atteint ce bloc car c'est le bloc else qui veut dire SINON, sous entendu "dans tous les autres cas".
5 - Deux façons de gérer les fonctions contenant un SI
RAPPEL : on sort d'une fonction et on fait disparaître toute la mémoire dédiée dès qu'on rencontre un return.
Version propre avec une seule "porte de sortie"
- AVANTAGE : plus facile de surveiller la correction de la fonction (le fait que la fonction réponde toujours correctement)
- DESAVANTAGE : il faut stocker la réponse dans une variable et lire ensuite séquentiellement la fonction jusqu'à trouver l'unique sortie.
1
2
3
4
5
6
7
8 |
|
Version avec plusieurs "portes de sortie"
- DéESAVANTAGE : moins facile à surveiller (plusieurs portes de sortie à contrôler).
- AVANTAGE : on n'a pas besoin en tant que lecteur humain de continuer à lire le reste du code lorsqu'on rencontre une sortie.
1
2
3
4
5
6
7 |
|
Ou encore :
1
2
3
4
5
6 |
|
Exemples
Voici quelques autres exemples d'utilisation pour mieux comprendre comment structurer vos demandes :
- La fonction trop_gentil() qui renvoie une note augmentée de +2 si la note d'entrée est inférieure à 10 et, sinon, +1 pour une note inférieure à 19.
- La fonction beaucoup_trop_gentil() qui renvoie une note augmentée de +5 si la note d'entrée est inférieure à 10 et, sinon, +3 dans les autres cas. La fonction ne doit jamais renvoyer de notes supérieures à 20 : on impose L8-L9 cette condition juste avant de renvoyer la réponse par l'unique porte de sortie.
- La fonction beaucoup_trop_gentil() pas top car elle possède plusieurs "portes de sortie" : on se retrouve à faire du copier-coller de la vérification des valeurs des sorties (L6-L7 et L12-L13). La correction de la fonction est plus compliquée à faire.
1
2
3
4
5
6 |
|
1
2
3
4
5
6
7
8
9
10 |
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14 |
|
6 - Tester une égalité avec Python
Pour tester l'égalité, on utilise un double signe égal a == b.
Cette expression est équivalente à la question "Les contenus des variables a et b sont-ils identiques ?"
7 - Prédicat
C'est simplement une fonction qui renvoie un booléen.
On parle de prédicat puisque la fonction prédit une propriété à partir des paramètres reçus.
Ce cas de figure est très courant en informatique : créer un prédicat (une fonction qui renvoie True ou False) ne requiert donc forcément pas d'utiliser un if : il suffit de fournir l'expression qu'on veut évaluer derrière votre return.
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
Le prédicat validant le semestre donnerait simplement ceci :
1
2
3 |
|
8 - Tester si une expression est évaluée à VRAI
Imaginons qu'on dispose d'un prédicat contient_le_mot() qui permet de tester si une chaine de caractères contient un mot qu'on recherche.
1
2 |
|
Un exemple d'utilisation :
>>> contient_le_mot("Je veux me plaindre de mes notes bla bla", "plaindre")
True
Bonne pratique de programmation
On pourrait ainsi lancer un traitement automatique de certains emails reçus en fonction de mots clés contenus dans des emails (par exemple le mot "montre" ou "viagra" ou "héritage"...) Voici comment faire :
1
2
3
4 |
|
Mauvaise pratique de programmation
Nous aurions pu écrire ceci mais c'est plus long et inutile puisque le principe est bien de faire le bloc si l'expression est évaluée à True :
1
2
3
4 |
|
9 - Tester si une expression est évaluée à FAUX
Imaginons qu'on veuille agir lorsqu'un mot n'est pas présent dans un message. On dispose d'un prédicat contient_le_mot() qui permet de savoir si un mot est contenu dans une chaîne de caractères.
Très mauvaise pratique de programmation
On pourrait donc produite une instruction conditionnelle if-elif comme ci-dessous (mais assez moche) :
1
2
3
4
5
6 |
|
C'est moche de dire de ne rien faire puis de donner le cas où on veut agir.
Assez mauvaise pratique de programmation
On peut faire mieux en agissant directement si le mot n'est pas présent en tapant ceci :
1
2
3
4 |
|
Ou même :
1
2
3
4 |
|
Cette fois, l'utilisation de l'opérateur d'égalité == ou de différence != ne semble pas superflue.
Bonne pratique de programmation
On peut faire mieux 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
On peut alors écrire plus proprement le fait d'agir uniquement si le mot n'apparaît pas :
1
2
3
4 |
|
10 - Le ET logique avec Python
Voici la table de vérité d'un ET :
Valeur de a | Valeur de b | a and b |
---|---|---|
True | True | True |
False | True | False |
True | False | False |
False | False | False |
A RETENIR : le ET n'est VRAI que lorsque toutes les entrées sont à VRAI.
11 - Le OU logique avec Python
Voici la table de vérité d'un OU :
Valeur de a | Valeur de b | a or b |
---|---|---|
True | True | True |
False | True | True |
True | False | True |
False | False | False |
A RETENIR : le OU n'est FAUX que si toutes les entrées sont FAUSSES.
12 - Convertir en booléen
La fonction native bool() permet de convertir n'importe quelle expression en booléen. Avec Python :
- Tout ce qui peut s'évaluer à zéro, vide ou inexistant donne False :
- 0,
- 0.0,
- "" (un string vide),
- None (la réponse d'une fonction qui n'a rien à dire en réponse),
- [] (un tableau vide),
- () (un tuple vide),
- {} (un dictionnaire vide)
- le reste sera évalué à True.
>>> bool(0)
False
>>> bool(0.0)
False
>>> bool(None)
False
>>> bool("")
False
>>> bool([])
False
>>> bool(1)
True
>>> bool(-10.2)
True
>>> bool("bonjour")
True
>>> bool([1])
True
13 - Instruction conditionnelle sans expression booléenne
En Python, on peut fournir une expression non booléenne derrière un if ou un elif : l'interpréteur Pyhon va alors cherhcer à l'interpréter en booléen de lui-même.
Si vous tapez if a:
Python va réagir comme si vous aviez tapé if bool(a):
Si a n'est pas vide ou 0, on effectura le bloc.
14 - Tester le remplissage d'un string ou d'un tableau
On peut tester si un tableau ou un string est vide et agir en conséquence en utilisant une simple instruction conditionnelle.
Voici comment agir de façon différente si le tableau n'est pas vide ou s'il est vide :
1
2
3
4
5 |
|
Ici if tab doit donc être traduit par "Si tab contient quelque chose d'évaluable par VRAI".
2 - Booléens et opérateurs booléens
1 - Booléens
Les ordinateurs n'ont que deux choix possibles lorsqu'on leur donne une proposition à tester (du style "Sommes-nous en 2025 ?"). La réponse est donc 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).
- 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 le résultat d'une expression booléenne dans une variable. Cette variable contiendra alors soit True, soit False.
02-A° Formuler en français la question équivalente aux différentes expressions booléennes dont les résultats seront stockés dans les variables c, d, e et f.
>>> a = 12
>>> b = 20
>>> c = b > a
>>> d = b < a
>>> e = b == a
>>> f = b != a
...CORRECTION...
>>> c = b > a
Le contenu de b est-il strictement supérieur au contenu de a ?
>>> d = b < a
Le contenu de b est-il strictement inférieur au contenu de a ?
>>> e = b == a
Le contenu de b est-il identique au contenu de a ?
>>> f = b != a
Le contenu de b est-il différent du contenu de a ?
Les questions équivalentes sont :
02-B° Trouver le contenu stocké dans les différentes variables c, d, e et f.
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
2 - Instruction ou expression ?
Une instruction va modifier l'état de la mémoire. L'affectation est l'instruction la plus fondamentale.
Une expression est un ensemble de valeurs et d'opérateurs pouvant être évaluée. L'évaluation d'une expression correspond à la recheche de sa valeur.
Si l'expression ne contient pas d'instruction, il n'y a pas de modification de l'état du programme.
Exemple d'affection utilisant une évaluation à droite :
>>> c = b > a
On peut dire que b > a est une expression (booléenne puisqu'elle va être évaluée à True ou False).
Par contre, c = b > a dans son ensemble est une instruction (une instruction d'affectation ici) puisqu'elle va modifier l'état de la variable c.
Exemple d'évaluation (la console affichant la valeur évaluée puisqu'on ne la redirige nulle part):
>>> "La" in 'Lalala'
True
Exemple d'instruction
>>> d = "La" in 'Lalala'
C'est bien une instruction puisque l'état de la mémoire est différent après application de cette instruction : on a créé ou modifié le contenu affecté à la variable d.
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.
3 - Instruction conditionnelle SI
3 - Structure générale des instructions conditionnelles SI - SINON SI - SINON
Quelque soit le langage, on retrouve toujours une structure qui ressemble à ceci :
1
2
3
4
5
6
7
8
9
10
11 |
|
Nombre de blocs
- Un unique bloc SI et il doit toujours être en première position
- 0, 1 ou autant de blocs SINON SI que vous voulez (il peut ne pas y en avoir)
- 0 ou 1 bloc SINON et il doit toujours être en dernière position : c'est le bloc par défaut. Si aucun autre n'a été activé, on prend celui-ci.
4 - Déroulement d'une séquence if-elif-else en Python
A SAVOIR IMPERATIVEMENT
L'interpréteur Python n'exécute que l'un des blocs A, B ou C d'une structure if-elif-else.
Il exécute les instructions du bloc de la première expression évaluée à True puis quitte la structure même si les autres expressions sont vraies également.
Exemple
Instructions Avant 1
Instructions Avant 2
if note > 11: # BLOC A
Instruction A1
Instruction A2
Instruction A3
elif note < 9: # BLOC B
Instruction B1
Instruction B2
Instruction B3
else: # BLOC C
Instruction C1
Instruction C2
Instructions Après 1
Instructions Après 2
Déroulement
Bloc A if : SI l'expression A (note > 11) est évaluée à True, il exécute A1-A2-A3 puis atteint directement Après 1. Sinon, il passe au bloc B.
Bloc B elif : SINON, SI l'expression B (note < 9) est évaluée à True, il exécute B1-B2-B3 puis atteint directement Après 1. Sinon, il passe au bloc C.
Bloc C else : on réalise forcément les instructions C1-C2 si on atteint ce bloc car c'est le bloc else qui veut dire SINON, sous entendu "dans tous les autres cas".
03° Tester la fonction suivante en lui fournisant différents paramètres entre 1980 et 2010 par exemple.
1
2
3
4
5
6
7
8
9
10 |
|
>>> creer_message(1981)
???
>>> creer_message(1991)
???
>>> creer_message(2021)
???
Questions :
- La fonction renvoie-t-elle systématiquement la même réponse pour 1980, 1991 et 2050 ?
- Ligne 4 : si le paramètre reponse contient 1987, comment est évaluée l'expression reponse > annee_creation_python ? Va-t-on alors activer la ligne 5 ?
- Ligne 6 : si le paramètre reponse contient 1987, comment est évaluée l'expression reponse < annee_creation_python ? Va-t-on activer la ligne 7 ?
- Quel est mot-clé correspondant à SI en Python ?
- Quel est mot-clé correspondant à SINON SI en Python ?
- Quel est mot-clé correspondant à 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(1981)
'Python a été créé après 1981'
>>> creer_message(1991)
'Oui, Python est sorti pour la première fois en 1991'
>>> creer_message(2021)
'Python a été créé avant 2021'
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 puisque l'expression booléenne n'est pas vraie.
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 à un des blocs d'une instruction conditionnelle.
On retrouve la syntaxe des déclarations de fonctions avec def et des boucles bornées avec for.
C'est l'indentation à 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.
05° L'interpréteur continue-t-il à effectuer le reste des tests à partir du moment où il valide l'un des blocs d'instructions ?
...CORRECTION...
L'interpréteur ne traitera bien que l'un des blocs.
Dès qu'il rencontre une expression évaluée VRAIE, il exécute les instructions du bloc correspondant puis quitte la structure conditionnelle SANS tester les possibilités restantes.
06° Compléter la fonction appreciation() ci-dessous. Elle doit renvoyer "Bien" si le paramètre note est strictement 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.
Version 2 valide (plusieurs sorties)
1
2
3
4
5
6
7
8
9
10
11
12
13 |
|
AVANTAGE : cette structure permet au lecteur humain de savoir immédiatement la réponse qui va être donner dans ce cas.
DESAVANTAGE : il va être plus difficile de vérifier et surveiller les réponses de cette fonction. C'est comme surveiller un batiment : c'est plus facile de contrôler les sorties s'il n'y a qu'une seule sortie.
Version 3 valide (plusieurs sorties, pas de else final)
Une autre personne pense qu'on peut encore faire plus rapide en supprimant le else final avec cette version 03. Cette version 03 est valide également puisque si on arrive en ligne 12, c'est que les autres return n'ont pas été rencontrés.
1
2
3
4
5
6
7
8
9
10
11
12 |
|
AVANTAGE : on gagne une ligne. Bof.
Version 4 incorrecte (une sortie, pas de else final)
Un enthousiaste pense du coup à modifier la première version et propose une version 04 (incorrecte attention).
1
2
3
4
5
6
7
8
9
10
11
12
13 |
|
Question
Expliquer 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.
5 - Deux façons de gérer les fonctions contenant un SI
RAPPEL : on sort d'une fonction et on fait disparaître toute la mémoire dédiée dès qu'on rencontre un return.
Version propre avec une seule "porte de sortie"
- AVANTAGE : plus facile de surveiller la correction de la fonction (le fait que la fonction réponde toujours correctement)
- DESAVANTAGE : il faut stocker la réponse dans une variable et lire ensuite séquentiellement la fonction jusqu'à trouver l'unique sortie.
1
2
3
4
5
6
7
8 |
|
Version avec plusieurs "portes de sortie"
- DéESAVANTAGE : moins facile à surveiller (plusieurs portes de sortie à contrôler).
- AVANTAGE : on n'a pas besoin en tant que lecteur humain de continuer à lire le reste du code lorsqu'on rencontre une sortie.
1
2
3
4
5
6
7 |
|
Ou encore :
1
2
3
4
5
6 |
|
Exemples
Voici quelques autres exemples d'utilisation pour mieux comprendre comment structurer vos demandes :
- La fonction trop_gentil() qui renvoie une note augmentée de +2 si la note d'entrée est inférieure à 10 et, sinon, +1 pour une note inférieure à 19.
- La fonction beaucoup_trop_gentil() qui renvoie une note augmentée de +5 si la note d'entrée est inférieure à 10 et, sinon, +3 dans les autres cas. La fonction ne doit jamais renvoyer de notes supérieures à 20 : on impose L8-L9 cette condition juste avant de renvoyer la réponse par l'unique porte de sortie.
- La fonction beaucoup_trop_gentil() pas top car elle possède plusieurs "portes de sortie" : on se retrouve à faire du copier-coller de la vérification des valeurs des sorties (L6-L7 et L12-L13). La correction de la fonction est plus compliquée à faire.
1
2
3
4
5
6 |
|
1
2
3
4
5
6
7
8
9
10 |
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14 |
|
Passons à la pratique :
✎ 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 "traduction inconnue pour cette couleur".
Remarque : nous verrons plus tard dans l'année un moyen plus efficace de traiter ceci. Ici, vous allez devoir écrire une longue succession de tests...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 |
|
4 - Prédicat : fonction renvoyant un booléen
Nous avons déjà vu l'opérateur d'égalité ==. Il permet de tester si une variable contient bien 5 par exemple.
Attention à ne pas confondre
- l'opérateur d'égalité == (deux signes =) et
- l'opérateur d'affectation = (un seul signe =).
Avec a == b, l'interpréteur comprend qu'il doit tester l'égalité des variables a et b. Il va donc évaluer cette expression et obtenir vrai ou faux.
Avec a = b, l'interpréteur comprend qu'il faut stocker b dans la variable a.
6 - Tester une égalité avec Python
Pour tester l'égalité, on utilise un double signe égal a == b.
Cette expression est équivalente à la question "Les contenus des variables a et b sont-ils identiques ?"
7 - Prédicat
C'est simplement une fonction qui renvoie un booléen.
On parle de prédicat puisque la fonction prédit une propriété à partir des paramètres reçus.
Ce cas de figure est très courant en informatique : créer un prédicat (une fonction qui renvoie True ou False) ne requiert donc forcément pas d'utiliser un if : il suffit de fournir l'expression qu'on veut évaluer derrière votre return.
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
Le prédicat validant le semestre donnerait simplement ceci :
1
2
3 |
|
09° Evaluer note >= 10 si le paramètre note vaut 7. Que va renvoyer la fonction valider_semestre() ?
1
2
3 |
|
...CORRECTION...
note >= 10
7 >= 10
10° 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 return note >= 10.
11° Compléter la fonction comparer() pour qu'elle renvoie True si les deux paramètres sont égaux. Aucune condition de type sur les deux paramètres.
1
2
3 |
|
...CORRECTION...
Il est probable que vous ayez 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 |
|
5 - Inversion d'un booléen avec not
Nous allons voir comment utiliser ces prédicats de manière élégante.
8 - Tester si une expression est évaluée à VRAI
Imaginons qu'on dispose d'un prédicat contient_le_mot() qui permet de tester si une chaine de caractères contient un mot qu'on recherche.
1
2 |
|
Un exemple d'utilisation :
>>> contient_le_mot("Je veux me plaindre de mes notes bla bla", "plaindre")
True
Bonne pratique de programmation
On pourrait ainsi lancer un traitement automatique de certains emails reçus en fonction de mots clés contenus dans des emails (par exemple le mot "montre" ou "viagra" ou "héritage"...) Voici comment faire :
1
2
3
4 |
|
Mauvaise pratique de programmation
Nous aurions pu écrire ceci mais c'est plus long et inutile puisque le principe est bien de faire le bloc si l'expression est évaluée à True :
1
2
3
4 |
|
12-A° Imaginons qu'on veuille tester si une moyenne est suffisante pour valider un bloc d'enseignement à l'université. Créons pour cela la fonction estValide().
1
2
3 |
|
Les deux utilisations ci-dessous sont-elles valides ? L'une des deux versions elle-est à privilégier ?
Version A
1
2 |
|
Version B
1
2 |
|
...CORRECTION...
Par défaut, Python évalue la condition et réalise les actions du bloc si la condtion est évaluée à True. Mais comme ici nous obtenons directement un booléen, pas la peine d'en rajouter : le cas A est suffisant et clair.
Ok |
|
Vous auriez pu taper ceci également, mais c'est inutile :
Ok mais bof bof |
|
Voyons maintenant, l'inverse : comment réaliser une action uniquement si on vous répond FAUX.
9 - Tester si une expression est évaluée à FAUX
Imaginons qu'on veuille agir lorsqu'un mot n'est pas présent dans un message. On dispose d'un prédicat contient_le_mot() qui permet de savoir si un mot est contenu dans une chaîne de caractères.
Très mauvaise pratique de programmation
On pourrait donc produite une instruction conditionnelle if-elif comme ci-dessous (mais assez moche) :
1
2
3
4
5
6 |
|
C'est moche de dire de ne rien faire puis de donner le cas où on veut agir.
Assez mauvaise pratique de programmation
On peut faire mieux en agissant directement si le mot n'est pas présent en tapant ceci :
1
2
3
4 |
|
Ou même :
1
2
3
4 |
|
Cette fois, l'utilisation de l'opérateur d'égalité == ou de différence != ne semble pas superflue.
Bonne pratique de programmation
On peut faire mieux 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
On peut alors écrire plus proprement le fait d'agir uniquement si le mot n'apparaît pas :
1
2
3
4 |
|
12-B° Imaginons qu'on veuille convoquer à un oral de rattrapage les étudiants ayant raté leur semestre. Nous voulons toujours utiliser la fonction estValide().
1
2
3 |
|
Les deux utilisations ci-dessous sont-elles valides ? L'une des deux versions elle-est à privilégier ?
Version A
1
2 |
|
Version B
1
2 |
|
...CORRECTION...
La version A est la plus élégante.
Ok et élégant |
|
Comme la fonction renvoie un booléen, nous pourrions également utiliser la version B mais c'est moins "propre" :
Ok mais bof bof |
|
Ok mais bof bof |
|
12-C° Quelle va être la ligne interprétée (L2 ou L4) si comparer() renvoie False sur cet appel.
1
2
3
4 |
|
...CORRECTION...
La ligne 1 va être progressivement évaluée de cette manière :
if not comparer(choix, m)
if not False
if True
Comme la condition de la ligne 1 donne True, on effectue son bloc et on exécute donc la fonction tache_1().
6 - ET / OU
Imaginons qu'on veuille créer une fonction est_valide() qui vérifie qu'une note est bien comprise entre 0 et 20.
1
2
3
4
5
6
7 | def est_valide(n:int) -> bool:
'''Prédicat qui renvoie True si n est un entier dans [0;20]'''
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 n de 15 par exemple.
1
2
3
4
5
6
7 | def est_valide(n:int) -> bool:
'''Prédicat qui renvoie True si n est un entier dans [0;20]'''
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 la console.
>>> 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 : que doivent valoir a et b pour que l'expression booléenne a and b soit évaluée à True ?
...CORRECTION...
L'expression n'est évaluée à True qui si les deux expressions a b sont 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 | def est_valide(n:int) -> bool:
'''Fonction qui renvoie True si n est un entier dans [0;20]'''
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 | def est_valide(n:int) -> bool:
'''Prédicat qui renvoie True si n est un entier dans [0;20]'''
return n > -1 and n < 21
|
10 - Le ET logique avec Python
Voici la table de vérité d'un ET :
Valeur de a | Valeur de b | a and b |
---|---|---|
True | True | True |
False | True | False |
True | False | False |
False | False | False |
A RETENIR : le ET n'est VRAI que lorsque toutes les entrées sont à VRAI.
Il existe également le OU
Un ET est évalué à VRAI uniquement lorsque toutes les entrées sont VRAIES. Le OU est évalué à FAUX uniquement lorsque toutes les entrées sont FAUSSES. 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-prédicat 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 répondre ? Voici la table de vérité d'un OU : A RETENIR : le OU n'est FAUX que si toutes les entrées sont FAUSSES. Attention, dans l'utilisation courante d'un OU dans une discussion, on indique souvent que c'est une chose ou alors une autre qui est possible, jamais les deux. Fromage ou dessert. Il pleut ou pas. Le ou du langage courant correspond à ce qu'on appelle en logique un OU exclusif : c'est l'un ou l'autre, pas les deux. Si vous dites 'Fromage ou dessert' à un informaticien, il prendra les deux ! Oui, le OU logique est bien évaluée à VRAI si les deux sont VRAIS.
Sinon, il est évalué à FAUX.
Globalement, dès qu'une condition est FAUX, le ET est FAUX.
Sinon, il est évalué à VRAI.
Globalement, dès qu'une condition est VRAI, le OU est VRAI.
Valeur de a
Valeur de b
a or b
True
True
?
False
True
?
True
False
?
False
False
?
a or b
...CORRECTION...
Valeur de a
Valeur de b
a or b
True
True
True
False
True
True
True
False
True
False
False
False
11 - Le OU logique avec Python
Valeur de a
Valeur de b
a or b
True
True
True
False
True
True
True
False
True
False
False
False
OU LOGIQUE différent que OU courant
7 - If sans condition booléenne ?
Avec un IF, on exécute un bloc tabulé si l'expression booléenne est True.
1
2
3
4 | if expression_booléenne_1:
fait un truc
elif expression_booléenne_2:
fait autre chose
|
Mais que se passe-t-il si on place une expression non booléenne derrière le if ou le elif ?
12 - Convertir en booléen
La fonction native bool() permet de convertir n'importe quelle expression en booléen. Avec Python :
- Tout ce qui peut s'évaluer à zéro, vide ou inexistant donne False :
- 0,
- 0.0,
- "" (un string vide),
- None (la réponse d'une fonction qui n'a rien à dire en réponse),
- [] (un tableau vide),
- () (un tuple vide),
- {} (un dictionnaire vide)
- le reste sera évalué à True.
>>> bool(0)
False
>>> bool(0.0)
False
>>> bool(None)
False
>>> bool("")
False
>>> bool([])
False
>>> bool(1)
True
>>> bool(-10.2)
True
>>> bool("bonjour")
True
>>> bool([1])
True
Pourquoi parler de cela ici ? Tout simplement à cause de la nature du if expression_booléenne.
Ce cas est facile à comprendre car vous savez maintenant que l'expression derrière le if va être évaluée à True ou False
- if a > b:
L'expression a > b est déjà une expression booléenne, il est donc inutile de tenter de la convertir en booléen en utilisant la fonction native bool(), mais on pourrait taper cela :
- if bool(a > b):
13 - Instruction conditionnelle sans expression booléenne
En Python, on peut fournir une expression non booléenne derrière un if ou un elif : l'interpréteur Pyhon va alors cherhcer à l'interpréter en booléen de lui-même.
Si vous tapez if a:
Python va réagir comme si vous aviez tapé if bool(a):
Si a n'est pas vide ou 0, on effectura le bloc.
19° Donner les contenus des variables r1, r2, r3, r4 obtenus après exécution du programme ci-dessous.
1
2
3
4
5
6
7
8
9
10 |
|
...CORRECTION...
r1 : avec le premier envoi, la condition de la ligne 3 est évaluée à True, et la fonction renvoie donc 20.
r2 : avec le premier envoi, la condition de la ligne 3 est évaluée à False car la variable n'est qu'une chaîne de caractères vide, et la fonction renvoie donc 10.
r3 : avec le premier envoi, la condition de la ligne 3 est évaluée à True, et la fonction renvoie donc 20.
r4 : avec le premier envoi, la condition de la ligne 3 est évaluée à False car la variable n'est qu'un tableau vide, et la fonction renvoie donc 10.
14 - Tester le remplissage d'un string ou d'un tableau
On peut tester si un tableau ou un string est vide et agir en conséquence en utilisant une simple instruction conditionnelle.
Voici comment agir de façon différente si le tableau n'est pas vide ou s'il est vide :
1
2
3
4
5 |
|
Ici if tab doit donc être traduit par "Si tab contient quelque chose d'évaluable par VRAI".
On peut maintenant réaliser une fonction qui peut nous aider à gérer les réservations d'un restaurant.
✎ 20-difficile° Donner et expliquer le contenu des variables possible et numero si elle existe.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 |
|
Le programme commence en ligne 21, le reste étant de la déclaration de fonctions.
21
22
23
24 |
|
- En L21, on déclare le tableau contenant les réservations de tables.
- En L23, on teste le fait qu'une table soit encore libre.
- En L24, on récupère un numéro de table disponible.
Pour répondre, il faudra suivre le déroulé exact du programme, expliquer lors des appels ce que contient tel ou tel paramètre... Tenter de comprendre le programme dans sa globalité, sans suivre réellement son cheminement n'a que peu de chance d'aboutir. Séquentialité.
Demandez de l'aide s'il le faut, ce n'est pas facile.
Activité publiée le 01 11 2020
Dernière modification : 04 10 2022
Auteur : ows. h.