Outils Conditions

Identification

Infoforall

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 : 5 questions

  questions 06-14-16-18

  question 20

DM 🏠 : Non

Documents de cours : open document ou pdf

1 - Booléens

(RAPPELS) 1.1 Booléen : vrai ou faux

Booléens

Lorsqu'on utilise certains opérateurs booléens, l'interpréteur évalue votre expression en répondant :

  • True si c'est vrai ou
  • False sinon.

Pas de réponse de type "peut être". Néanmoins, la demande peut provoquer une erreur.

Opérateurs renvoyant une valeur booléenne

  • relation strictement supérieur avec >
  • int|float > int|float -> bool

    Le signe | veut dire OU. On peut donc placer un entier ou un flottant.

    >>> 40 > 30 True

    On pose la question suivante à l'interpréteur Python : "40 est-il strictement supérieur à 30 ?".

    str > str -> bool

    >>> "crocodile" > "tortue" False

    On pose la question suivante à l'interpréteur Python : "Le mot "crocodile" est-il derrière le mot "tortue" dans le dictionnaire ?".

    On voit qu'on utilise ici l'ordre lexicographique, l'ordre du dictionnaire (si tout est en minuscule).

    Dans une autre activité, nous détaillerons un peu plus comment cela fonctionne, notamment la gestion des majuscules ou des autres caractères.


  • opérateur d'égalité avec ==
  • Puisque = est déjà utilisé pour l'affectation des variables (a = 50 par exemple), les concepteurs de Python ont choisi la syntaxe d'un double signe égal pour le test d'égalité.

    >>> 40 == 3 * 10 False

    On pose la question suivante à l'interpréteur Python : "40 est-il identique à 3 * 10 ?".

    >>> 40 == 4 * 10 True

    On pose la question suivante à l'interpréteur Python : "40 est-il identique à 4 * 10 ?".

    >>> 0.3 == 3 * 0.1 False

    On pose la question suivante à l'interpréteur Python : "0.3 est-il identique à 3 * 0.1 ?". Pourquoi obtient-on False ? Simplement car 0.1 n'a pas été mémorisé de façon exacte, et donc 3 * presque 0.1, ca ne donne pas presque 0.3 !


  • opérateur de différence avec !=
  • Puisque n'est pas facilement accessible sur un clavier, les concepteurs de Python ont choisi la syntaxe != pour le test de différence. Dans d'autres langages, c'est parfois <>.

    >>> 40 != 3 * 10 True

    On pose la question suivante à l'interpréteur Python : "40 est-il différent de 3 * 10 ?".

    >>> 40 != 4 * 10 False

    On pose la question suivante à l'interpréteur Python : "40 est-il différent de 4 * 10 ?".


  • autres opérateurs de comparaison :
  • >>> 40 < 30 False

    On pose la question suivante à l'interpréteur Python : "40 est-il strictement inférieur à 30 ?".

    >>> 40 <= 30 False

    On pose la question suivante à l'interpréteur Python : "40 est-il inférieur ou égal à 30 ?".

    >>> 40 >= 30 False

    On pose la question suivante à l'interpréteur Python : "40 est-il supérieur ou égal à 30 ?".


  • appartenance avec in
  • Le mot-clé in permet de savoir si un élément a est présent dans un élément b : a in b

    Si la réponse est True, c'est que a apparaît dans b. Sinon, la réponse sera False.

    Voici un moyen de tester facilement si quelqu'un d'allergique au soja peut manger un produit dont on connaît la composition :

    >>> "soja" in "Sucre ; huile de colza ; eau ; chocolat en poudre 15 % (sucre, pâte de cacao) ; farine de blé ; poudre d’œuf ; stabilisants : glycérol, gomme xanthane ; cacao en poudre 2,5 % ; poudre à lever : E450, E500 ; amidon de blé ; conservateur : E202 ; sel. Traces de lait." False

    La question posée est Le mot "soja" apparaît-il dans la composition fournie" ?

    Et si vous étiez intolérant au blé ?

    >>> "blé" in "Sucre ; huile de colza ; eau ; chocolat en poudre 15 % (sucre, pâte de cacao) ; farine de blé ; poudre d’œuf ; stabilisants : glycérol, gomme xanthane ; cacao en poudre 2,5 % ; poudre à lever : E450, E500 ; amidon de blé ; conservateur : E202 ; sel. Traces de lait." True

    La question posée est Le mot "blé" apparaît-il dans la composition fournie" ?

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 stocker le résultat d'une expression booléenne dans une variable. Cette variable contiendra alors soit True, soit False.

Questions

  1. 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.
  2. 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...

Les questions équivalentes sont :

>>> 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 ?

Pour les valeurs, il suffit de vérifier :

>>> a = 12 >>> b = 20 >>> c = b > a >>> c True >>> d = b < a >>> d False >>> e = b == a >>> e False >>> f = b != a >>> f True
(RAPPELS) 1.2 Expression - Instruction - Affectation

Expression

Une expression est un ensemble de valeurs associées à des opérateurs. L'interpréteur peut évaluer l'expression pour en fournir la valeur.

Une expression ne modifie pas l'état du programme.. Elle fournit simplement une valeur, sans la stocker définitivement.

Dans un programme :

1
"bon" * 2

Ce programme n'a aucun effet, ni en mémoire, ni à l'affichage. Sa ligne est bien simplement une expression.

Dans la console interactive :

>>> "bon" * 2 'bonbon'

Attention, l'affichage obtenu est juste dû au fait qu'on soit dans la console : puisqu'on ne fait rien du résultat de l'expression, il est redirigé vers la sortie console. La même ligne n'aurait aucun effet dans un programme.

Instruction

Une instruction modifie l'état du programme (soit sa mémoire, soit en modifiant l'IHM).

  • L'instruction la plus fondamentale est l'affectation : on crée une variable en mémoire.
  • Dans un programme :

    1
    a = 5

    Dans la console :

  • L'utilisation d'une méthode du module Turtle est bien une instruction : on modifie l'affichage à l'écran et donc l'état de l'interface graphique.
Exemples
>>> "bon" * 2 # EXPRESSION (comme elle est seule et qu'on est dans la console, on obtient son affichage) 'bonbon' >>> a = "bon" * 2 # INSTRUCTION : AFFECTATION >>> print("bon" * 2) # INSTRUCTION (on agit sur l'IHM Console) bonbon

Notez bien que la console Python affiche le résultat d'une expression non redirigée ailleurs.

(RAPPELS) 1.3 - Créer un booléen avec bool()

La fonction native bool() reçoit une donnée quelconque et renvoie True ou False.

!!! A SAVOIR PAR COEUR !!!

En Python, un contenu VIDE ou NUL est évalué à False si on demande un résulat booléen.

Dans tous les autres cas, le résultat est True.

D'où l'intérêt de savoir ce que veut dire nul ou vide pour les différents types de base.

Voici quelques exemples d'évaluation en booléen :

>>> bool(0) False >>> bool(5) True >>> bool(5.2) True >>> bool(0.0) False >>> bool("5") True >>> bool("5.2") True >>> bool("bonjour") True >>> bool("") False

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, SINON SI, SINON

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.

(RAPPELS) 2.1 Instruction conditionnelle

Une instruction conditionnelle permet d'exécuter un bloc d'instructions uniquement si la condition évaluée est vraie (True en Python).

Ci-dessous, un exemple où on change l'appréciation si la note est bonne (if en anglais)

1 2 3 4 5 6
fatigue = "En forme !" appreciation = "Moyen" note = 20 if note > 15: appreciation = "Très bien" fatigue = "Grosse fatigue"

TABULATION : le bloc d'instructions à effectuer est décalé de 4 espaces (ligne 5). Ce décalage permet à l'intepréteur Python de signaler le début et la fin du bloc. La ligne 6 n'appartient donc pas au bloc.

Déroulé pour note = 20 : L1-L2-L3-L4-L5-L6

Déroulé pour note = 10 : L1-L2-L3-L4-L6

Traduction :

  • L3 : note vaut 20.
  • L4 : si la note fournie est strictement supérieure à 15
  • L5 tabulée : alors appreciation passe à "Très bien".
  • L6 : fatigue passe à "Grosse fatigue" (sans condition car pas de tabulation).
2.2 Instruction conditionnelle : structure générale

Quelque soit le langage, on retrouve toujours une structure qui ressemble à ceci :

1 2 3 4 5 6 7 8 9 10 11
SI une expression booléenne A est vraie # BLOC A (unique et obligatoire) Instruction A1 Instruction A2 SINON SI une expression booléenne B est vraie # BLOC B (optionnel(s)) Instruction B1 Instruction B2 SINON (dans tous les autres cas) # BLOC C (unique mais optionnel) Instruction C1 Instruction C2

Nombre de blocs

  • Un unique bloc SI et il doit toujours être en première position
  • 0, 1, 2 ou autant de blocs SINON SI que vous voulez
  • 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.
2.3 Instruction conditionnelle : un seul bloc exécuté

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.

Un exemple de déroulement
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
Instructions Avant 1 Instructions Avant 2 if note > 11: # BLOC A (unique et obligatoire) Instruction A1 Instruction A2 Instruction A3 elif note < 9: # BLOC B (optionnel(s)) Instruction B1 Instruction B2 Instruction B3 else: # BLOC C (unique et optionnel) Instruction C1 Instruction C2 Instructions Après 1 Instructions Après 2

Bloc A if : SI l'expression A (note > 11) est évaluée à True,
il exécute L1-L2-L4-L5-L6-L7-L18-L19.

Bloc B elif : SINON, SI l'expression B (note < 9) est évaluée à True, cela veut dire que la note n'est pas supérieure à 11 mais inférieure à 9.
Il exécute L1-L2-L4-L9-L10-L11-L12-L18-L19.

Bloc C else : on atteint ce bloc si la note n'est ni supérieure à 11, ni inférieuree à 9. C'est donc qu'elle vaut 9, 10 ou 11.
Il exécute L1-L2-L4-L9-L14-L15-L16-L18-L19.

02° 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
def creer_message(reponse:int) -> str: """Renvoie un string en fonction de la réponse de l'utilisateur""" annee_creation_python = 1991 if reponse > annee_creation_python: message = f"Python a été créé avant {reponse}" elif reponse < annee_creation_python: message = f"Python a été créé après {reponse}" else: message = f"Oui, Python est sorti pour la première fois en {reponse}" return message
>>> creer_message(1981) ??? >>> creer_message(1991) ??? >>> creer_message(2021) ???

Questions :

  1. Quel est mot-clé correspondant à SI en Python ?
  2. Quel est mot-clé correspondant à SINON SI en Python ?
  3. Quel est mot-clé correspondant à SINON en Python ?
  4. Donner les lignes suivies par l'interpréteur si lance creer_message(1981).
  5. Donner les lignes suivies par l'interpréteur si lance creer_message(1991).
  6. Donner les lignes suivies par l'interpréteur si lance creer_message(2021).

...CORRECTION...

  1. Le SI se code avec le mot-clé if.
  2. Le SINON SI se code avec le mot-clé elif.
  3. Le SINON (tout court) se code avec le mot-clé else.
  4. Lignes suivies par l'interpréteur si lance creer_message(1981) 
  5. L1 (reponse = 81) - L3 - L4(False) - L6(True) - L7 - L10

  6. Lignes suivies par l'interpréteur si lance creer_message(1991) 
  7. L1 (reponse = 81) - L3 - L4(False) - L6(False) - L8 - L9 - L10

  8. Lignes suivies par l'interpréteur si lance creer_message(2021) 
  9. L1 (reponse = 81) - L3 - L4(True) - L5 - L10

03° Quelques questions générales :

  1. Pourquoi ne place-t-on pas de condition derrière else, contrairement à if ou elif ?
  2. Que trouve-t-on à la fin de chacune des lignes contenant if, elif ou else ?
  3. Comment sont positionnées les instructions conditionnelles par rapport aux mots-clés précédents ?
  4. L'interpréteur continue-t-il à effectuer le reste des tests à partir du moment où il valide l'un des blocs d'instructions ?

...CORRECTION...

  1. else signifie SINON. C'est le cas par défaut, celui qu'on effectue si aucun des tests précédents n'a fonctionné. Il n'a donc aucune condition : si on parvient à lui, c'est que le reste a échoué.
  2. On finit chaque condition par  : .
  3. On retrouve la structure d'une fonction ou d'un for : on décale de 4 espaces pour signaler les limites du bloc.
  4. 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.

04° 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. Contrainte : on ne veut qu'un seul return.

1 2 3 4 5 6 7 8
def appreciation(note): """Renvoie un string correspondant à l'appréciation voulue :: param note(str) :: une note dans [0;20] :: return (str) :: l'appréciation correspondante """ pass

...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
def appreciation(note): """Renvoie un string correspondant à l'appréciation voulue :: param note(str) :: une note dans [0;20] :: return (str) :: l'appréciation correspondante """ if note > 13: app = "Bien" elif note < 9: app = "Insuffisant" else: app = "Moyen" return app

05° 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
def appreciation_v2(note): """Renvoie un string correspondant à l'appréciation voulue :: param note(str) :: une note dans [0;20] :: return (str) :: l'appréciation correspondante """ if note > 13: return "Bien" elif note < 9: return "Insuffisant" else: return "Moyen"

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
def appreciation_v3(note): """Renvoie un string correspondant à l'appréciation voulue :: param note(str) :: une note dans [0;20] :: return (str) :: l'appréciation correspondante """ if note > 13: return "Bien" elif note < 9: return "Insuffisant" return "Moyen"

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
def appreciation_v4(note): """Renvoie un string correspondant à l'appréciation voulue :: param note(str) :: une note dans [0;20] :: return (str) :: l'appréciation correspondante """ if note > 13: app = "Bien" elif note < 9: app = "Insuffisant" app = "Moyen" return app

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.

2.4 Instruction conditionnelle et fonction

RAPPEL : on sort d'une fonction et on fait disparaître l'espace des noms dédié 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
    def appreciation(note): if note > 13: app = "Bien" elif note < 9: app = "Insuffisant" else: app = "Moyen" return app
Version avec plusieurs "portes de sortie"
  • DESAVANTAGE : 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
    def appreciation(note): if note > 13: return "Bien" elif note < 9: return "Insuffisant" else return "Moyen"

    Ou encore :

    1 2 3 4 5 6
    def appreciation(note): if note > 13: return "Bien" elif note < 9: return "Insuffisant" return "Moyen"
Exemple

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.
  • 1 2 3 4 5 6
    def trop_gentil(note): if note < 10: note = note + 2 elif note < 19: note = note + 1 return note
  • 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.
  • 1 2 3 4 5 6 7 8 9 10
    def beaucoup_trop_gentil(note): # Première modification if note < 10: note = note + 5 else: note = note + 3 # Vérification avant envoi if note > 20: note = 20 return note
  • 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 7 8 9 10 11 12 13 14
    def beaucoup_trop_gentil(note): # Première modification if note < 10: note = note + 5 # Vérification avant envoi if note > 20: note = 20 return note else: note = note + 3 # Vérification avant envoi if note > 20: note = 20 return note

Passons à la pratique :

✎ 06° 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 : on veut une structure if-elif if-else. Mais nous sommes d'accord qu'un dict aurait mieux fait l'affaire !

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
def traduction(color): """Renvoie un string correspondant à la traduction de la couleur ANG -> FR :: param color(str) :: une couleur en anglais :: return (str) :: la traduction en français du string précédent .. exemples .. >>> traduction('green') 'vert' >>> traduction('grine') 'traduction inconnue pour cette couleur' """ couleur = "traduction inconnue pour cette couleur" return couleur

3 - Prédicat : fonction renvoyant un booléen

3.1 Opérateurs == et =

Attention à ne pas confondre

  • l'opérateur d'égalité de contenu ==
  • l'opérateur d'affectation =

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 si les deux contenus sont les mêmes.

Avec a = b, l'interpréteur comprend qu'il faut stocker b dans la variable a. On génère donc un alias.

3.2 FONCTION : Prédicat

On peut nommer de cette façon une fonction qui renvoie toujours un booléen : elle répondra soit True soit False.

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 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
def est_valide(note:int) -> bool: """Prédicat qui renvoie True si la note est supérieure ou égale à 10""" return note >= 10

07° Que va renvoyer la fonction est_valide() si le paramètre note vaut 7 ?

1 2 3
def est_valide(note:int) -> bool: """Prédicat qui renvoie True si la note est supérieure ou égale à 10""" return note >= 10

...CORRECTION...

note >= 10

7 >= 10

False

08° Un élève propose cette version : est-elle bonne, fausse, correcte mais inutilement longue ?

1 2 3 4 5 6
def est_valide(note:int) -> bool: """Prédicat qui renvoie True si la note est supérieure ou égale à 10""" if note >= 10: return True else: return False

...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.

09° Compléter la fonction- prédicat 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
def comparer(proposition, mystere) -> bool: """Prédicat qui renvoie True si les deux paramètres sont égaux""" pass

...CORRECTION...

Il est probable que vous ayez tapé quelque chose qui ressemble à cela :

1 2 3 4 5 6
def comparer(proposition, mystere) -> bool: """Prédicat qui renvoie True si les deux paramètres sont égaux, False sinon""" if proposition == mystere: return True else: return False

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
def comparer(proposition, mystere) -> bool: """Prédicat qui renvoie True si les deux paramètres sont égaux, False sinon""" if proposition == mystere: return True return False

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
def comparer(proposition, mystere) -> bool: """Renvoie True si les deux paramètres sont égaux, False sinon""" return proposition == mystere

4 - Opérateurs booléens

Nous allons voir comment décrire certaines conditions logiques de façon plus élégante et concise qu'avec une suite de if-elif-else.

Vous avez déjà vu des opérations qui renvoient un booléen. En voici trois avec leur signature :

L'opérateur d'appartenance

type_quelconque in type_structure -> bool

L'opérateur d'égalité de contenu

un_type_quelconque == un_type_quelconque -> bool

L'opérateur de différence de contenu

un_type_quelconque != un_type_quelconque -> bool

Nous allons maintenant voir les opérateurs booléens : ils renvoient un booléen mais doivent également recevoir des booléens en entrée.

4.1 Instruction conditionnelle : prédicat à True

RAPPEL : un prédicat est une fonction qui répondra True ou False sur toutes les entrées qu'on lui fournit.

Présentation du prédicat-exemple

Imaginons qu'on dispose d'un prédicat contient() qui permet de tester si une chaine de caractères contient un mot précis qu'on recherche, en comparant les deux en minuscules.

1 2 3 4 5
def contient(chaine:str, mot:str) -> bool: """Prédicat qui renvoie True si le mot est dans le string""" chaine_minus = chaine.lower() # La chaine mais en miniscules mot_minus = mot.lower() # Le mot mais en miniscules return mot_minus in chaine_minus

Un exemple d'utilisation :

>>> contient("Je veux me plaindre de mes notes bla bla", "PLAINDRE") True
Bonne pratique de programmation

On se souvient qu'on exécute le bloc si l'expression booléenne fournie derrière le if est évaluée à True.

Voici un programme qui permet de récupérer tous les plats qui contiennent des poivrons parmi une liste de plats qu'on aime bien par exemple :

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
plats = [ "crêpes au sucre: farine de blé; oeufs; lait; sucre", "pates carbonara : pâtes(blé); fromage; lardon(porc); crême épaisse; basilic", "moules frites : moule; vin blanc; oignons; persil; frites(pommes de terre)", "ratatouille : poivrons verts; poivrons rouges; aubergines; courgettes; tomates; oignons; ail; thym; laurier; persil", "boeuf aux carottes : boeuf; carottes; oignons; vin blanc; ail" "poulet basquaise : tomates; poivrons rouges; poivrons verts; oignons; poulet; thym; laurier; persil" ] def contient(chaine:str, mot:str) -> bool: """Prédicat qui renvoie True si le mot est dans le string""" chaine_minus = chaine.lower() # La chaine mais en miniscules mot_minus = mot.lower() # Le mot mais en miniscules return mot_minus in chaine_minus for plat in plats: # pour chaque plat du tableau plats if contient(plat, "Poivrons"): # si le plat contient des poivrons print(plat)

On voit donc qu'il suffit de placer le prédicat : s'il est interprété à True, on effectue le bloc. Sinon, non.

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 :

16 17 18
for plat in plats: # pour chaque plat du tableau plats if contient(plat, "Poivrons") == True: # si le plat contient des poivrons print(plat)

Evitez d'utiliser cette version : elle fonctionne mais montre que vous n'avez pas vraiment compris le principe du if.

10° Imaginons qu'on veuille tester si une moyenne est suffisante pour valider un bloc d'enseignement à l'université. Créons pour cela la fonction est_valide().

1 2 3
def est_valide(note:int) -> bool: """Prédicat qui renvoie True si la note est supérieure ou égale à 10""" return note >= 10

Les deux utilisations ci-dessous sont-elles valides ? L'une des deux versions elle-est à privilégier ?

Version A

1 2
if est_valide(15): print(Semestre validé. Passage en deuxième année)

Version B

1 2
if est_valide(15) == True: print(Semestre validé. Passage en deuxième année)

...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
if est_valide(15):

Vous auriez pu taper ceci également, mais c'est inutile :

Ok mais bof bof
if est_valide(15) == True:

Voyons maintenant, l'inverse : comment réaliser une action uniquement si on vous répond FAUX.

4.2 Instruction conditionnelle : not pour tester un prédicat à False

Imaginons qu'on veuille récupérer les plats qui ne contiennent pas de poivron. On dispose du prédicat contient() qui permet de savoir si un mot (un ingrédient par exemple) est contenu dans une chaîne de caractères (la recette par exemple).

Très mauvaise pratique de programmation

A éviter absolument !

On veut agir lorsque le prédicat est évalué à False. De façon naïve, on pourrait se dire : si le prédicat est vrai, on ne fait rien, sinon on agit.

16 17 18 19 20
for plat in plats: if contient_le_mot(plat, "poivron"): pass else: print(plat)
Assez mauvaise pratique de programmation

On se souvient qu'on exécute le bloc si l'expression booléenne fournie derrière le if est évaluée à True.

On pourrait donc placer comme expression le fait que le prédicat soit évaluée à False !

16 17 18
for plat in plats: # pour chaque plat du tableau plats if contient(plat, "Poivrons") == False: # si le plat ne contient pas de poivron print(plat)

Evitez d'utiliser cette version : nous allons voir ci-dessous qu'il existe une meilleure façon de faire, celle qui sera utiliser par n'importe quel développeur.

Bonne pratique de programmation : utiliser not

On peut faire mieux en utilisant le mot-clé not : ce mot-clé inverse la valeur du booléen situé derrière lui.

not bool -> bool

>>> b = False >>> b False >>> not b True

On peut alors écrire plus proprement le fait d'agir uniquement si le mot "Poivron" n'apparaît pas :

16 17 18
for plat in plats: # pour chaque plat du tableau plats if not contient(plat, "Poivrons"): # si le plat ne contient pas de poivron print(plat)

Le programme dans sa totalité :

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
plats = [ "crêpes au sucre: farine de blé; oeufs; lait; sucre", "pates carbonara : pâtes(blé); fromage; lardon(porc); crême épaisse; basilic", "moules frites : moule; vin blanc; oignons; persil; frites(pommes de terre)", "ratatouille : poivrons verts; poivrons rouges; aubergines; courgettes; tomates; oignons; ail; thym; laurier; persil", "boeuf aux carottes : boeuf; carottes; oignons; vin blanc; ail" "poulet basquaise : tomates; poivrons rouges; poivrons verts; oignons; poulet; thym; laurier; persil" ] def contient(chaine:str, mot:str) -> bool: """Prédicat qui renvoie True si le mot est dans le string""" chaine_minus = chaine.lower() # La chaine mais en miniscules mot_minus = mot.lower() # Le mot mais en miniscules return mot_minus in chaine_minus for plat in plats: # pour chaque plat du tableau plats if not contient(plat, "Poivrons"): # si le plat ne contient pas de poivron print(plat)

11° Imaginons qu'on veuille convoquer à un oral de rattrapage les étudiants ayant raté leur semestre. Nous voulons toujours utiliser la fonction est_valide().

1 2 3
def est_valide(note:int) -> bool: """Prédicat qui renvoie True si la note est supérieure ou égale à 10""" return note >= 10

Les deux utilisations ci-dessous sont-elles valides ? L'une des deux versions elle-est à privilégier ?

Version A

1 2
if not est_valide(15): print(Semestre raté. Convocation à l'oral)

Version B

1 2
if est_valide(15) == False: print(Semestre raté. Convocation à l'oral)

...CORRECTION...

La version A est la plus élégante.

Ok et élégant
if not est_valide(15):

Comme la fonction renvoie un booléen, nous pourrions également utiliser la version B mais c'est moins "propre" :

Ok mais bof bof
if est_valide(15) == False:
Ok mais bof bof
if est_valide(15) != True:

12° Quelle va être la ligne interprétée (L2 ou L4) si comparer() renvoie False sur cet appel.

1 2 3 4
if not comparer(choix, m): tache_1() else: tache_2()

...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().

4.3 Instruction conditionnelle : and pour utiliser plusieurs conditions en même temps

Imaginons qu'on veuille récupérer les plats qui contiennent du poivron et de l'aubergine. On dispose du prédicat contient() qui permet de savoir si un mot (un ingrédient par exemple) est contenu dans une chaîne de caractères (la recette par exemple).

Méthode possible mais problématique dans certains cas

On commence par filtrer sur les poivrons et on rajoute une instruction conditionnelle dans la première.

16 17 18 19
for plat in plats: if contient_le_mot(plat, "poivron"): if contient_le_mot(plat, "aubergine"): print(plat)

Si on ne doit rien faire lorsque c'est faux, c'est correct.

Par contre, si on doit agir lorsque ce n'est pas vrai, cela pose problème puisqu'il est possible qu'on soit obligé de faire du copier-coller ou qu'on oublie un cas.

16 17 18 19 20 21 22 23
for plat in plats: if contient_le_mot(plat, "poivron"): if contient_le_mot(plat, "aubergine"): print(plat) else: faire_un_truc() else: faire_un_truc()
Bonne pratique de programmation : utiliser and

On peut faire mieux en utilisant le mot-clé and : ce mot-clé est un opérateur booléen qui

  • renvoie Vrai uniquement si les entrées sont toutes vraies
  • renvoie Faux dans tous les autres cas.

bool and bool -> bool

>>> a = True >>> b = True >>> a and b True >>> b = False >>> a and b False

Pour afficher proprement les plats qui contiennent des poivrons et des aubergines :

16 17 18
for plat in plats: # pour chaque plat du tableau plats if contient(plat, "Poivron") and contient(plat, "Aubergine"): # si le plat contient poivrons ET aubergines print(plat)

Notez bien la présence d'une condition à gauche et à droite du mot-clé and.

De plus, si on veut agir lorsque ce n'est pas vrai, la structure ne nécessite plus de faire des copier-coller :

16 17 18 19 20
for plat in plats: # pour chaque plat du tableau plats if contient(plat, "Poivron") and contient(plat, "Aubergine"): # si le plat contient poivrons ET aubergines print(plat) else: # sinon, il en manque au moins un des deux faire_un_truc()

Le programme dans sa totalité :

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
plats = [ "crêpes au sucre: farine de blé; oeufs; lait; sucre", "pates carbonara : pâtes(blé); fromage; lardon(porc); crême épaisse; basilic", "moules frites : moule; vin blanc; oignons; persil; frites(pommes de terre)", "ratatouille : poivrons verts; poivrons rouges; courgettes; tomates; oignons; ail; thym; laurier; persil", "boeuf aux carottes : boeuf; carottes; oignons; vin blanc; ail" "poulet basquaise : tomates; poivrons rouges; poivrons verts; oignons; poulet; thym; laurier; persil" ] def contient(chaine:str, mot:str) -> bool: """Prédicat qui renvoie True si le mot est dans le string""" chaine_minus = chaine.lower() # La chaine mais en miniscules mot_minus = mot.lower() # Le mot mais en miniscules return mot_minus in chaine_minus for plat in plats: # pour chaque plat du tableau plats if contient(plat, "Poivron") and contient(plat, "Aubergine"): # si le plat contient poivrons ET aubergines print(plat)
4.4 Table de vérité du and

Voici la table de vérité de l'opérateur ET :

Valeur de a Valeur de b a and b
False False False
False True False
True False False
True True True

A RETENIR : le ET est VRAI uniquement lorsque toutes les entrées sont à VRAI.

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 l'opérateur and qui permet d'associer plusieurs conditions.

Revoyons 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 une autre version de cette fonction. 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
4.5 Instruction conditionnelle : or pour utiliser plusieurs conditions au choix

Imaginons qu'on veuille récupérer les plats qui contiennent soit du poivron, soit de l'aubergine, voire les deux à la fois. On dispose du prédicat contient() qui permet de savoir si un mot (un ingrédient par exemple) est contenu dans une chaîne de caractères (la recette par exemple).

Méthode possible mais qui nécessite du copier-coller

On commence par filtrer sur les poivrons, sinon, on filtre sur les aubergines.

16 17 18 19 20
for plat in plats: if contient_le_mot(plat, "poivron"): print(plat) elif contient_le_mot(plat, "aubergine"): print(plat)

Ici, on a bien deux fois la même instruction sur les lignes 18 et 20.

Bonne pratique de programmation : utiliser or

On peut faire mieux en utilisant le mot-clé or : ce mot-clé est un opérateur booléen qui

  • renvoie Faux uniquement si les entrées sont toutes fausses
  • renvoie Vrai dans tous les autres cas (c'est à dire, lorsque une des entrées au moins est vraie).

bool or bool -> bool

>>> a = True >>> b = True >>> a or b True >>> b = False >>> a or b True

Pour afficher proprement les plats qui contiennent des poivrons OU des aubergines, ou les deux :

16 17 18
for plat in plats: # pour chaque plat du tableau plats if contient(plat, "Poivron") or contient(plat, "Aubergine"): # si le plat contient poivrons Ou aubergines print(plat)

Notez bien la présence d'une condition à gauche et à droite du mot-clé or.

Le programme dans sa totalité :

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
plats = [ "crêpes au sucre: farine de blé; oeufs; lait; sucre", "pates carbonara : pâtes(blé); fromage; lardon(porc); crême épaisse; basilic", "moules frites : moule; vin blanc; oignons; persil; frites(pommes de terre)", "ratatouille : poivrons verts; poivrons rouges; courgettes; tomates; oignons; ail; thym; laurier; persil", "boeuf aux carottes : boeuf; carottes; oignons; vin blanc; ail" "poulet basquaise : tomates; poivrons rouges; poivrons verts; oignons; poulet; thym; laurier; persil" ] def contient(chaine:str, mot:str) -> bool: """Prédicat qui renvoie True si le mot est dans le string""" chaine_minus = chaine.lower() # La chaine mais en miniscules mot_minus = mot.lower() # Le mot mais en miniscules return mot_minus in chaine_minus for plat in plats: # pour chaque plat du tableau plats if contient(plat, "Poivron") or contient(plat, "Aubergine"): # si le plat contient poivrons OU aubergines print(plat)
4.6 Table de vérité du or

Le OU logique (celui de Python)

Voici la table de vérité de l'opérateur OU :

Valeur de a Valeur de b a or b
False False False
False True True
True False True
True True True

A RETENIR : le OU est FAUX uniquement lorsque toutes les entrées sont à FAUX.

Le OU exclusif

Le OU logique n'est pas celui de la vie de tous les jours. Si on vous dit "fromage ou dessert" à la cantine, cela veut dire malheureusement que vous ne pouvez en prendre qu'un.

Ce OU particulier se nomme le OU-EXCLUSIF en informatique, XOR an anglais. Si deux entrées sont vraies, le XOR sera faux.

Voici sa table de vérité :

Valeur de a Valeur de b a xor b
False False False
False True True
True False True
True True False

17° Compléter la table de vérité du OU :

Valeur de a Valeur de b a or b
True True ?
False True ?
True False ?
False False ?

Cela revient à chercher cela avec Python :

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

✎ 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 ?

  • A : return n >= 0 or n <= 20
  • B : return n <= 0 or n >= 20
  • C : return n > 0 or n < 20
  • D : return n < 0 or n > 20
4.7 Table de vérité du not

Voici la table de vérité de l'opérateur NON :

Valeur de a not a
False True
True False
4.8 Priorité des opérateurs logiques (P.A.C.Bo)

Entre eux
  • D'abord not
  • Ensuite and (équivalent de la multiplication)
  • Enfin or (équivalent de l'addition)
Par rapport aux autres opérateurs : P.A.C.Bo
  • P - Les plus prioritaires : les parenthèses ()
  • A - Ensuite les opérateurs arithmétiques
    • **
    • * / // %
    • + -
  • C - Ensuite les opérateurs de comparaison
    • les opérateurs d'appartenance in et not in
    • les opérateurs de comparaison supérieur et inférieur : >, >=...
    • les opérateurs d'égalité et différence ==, !=
  • BO - Ensuite les opérateurs logiques booléens
    • not
    • and
    • or
  • Les moins prioritaires : if, elif, else
Exemple

Inutile de savoir le refaire par coeur : en cas de doute, mettez des parenthèses. C'est l'habitude qui créera la connaissance de l'ordre P.A.C.Bo

if not a + 8 > b * 2 and a > 0

Op. Arithmétiques : if not (a + 8) > (b * 2) and a > 0

O. de Comparaison : if not ((a + 8) > (b * 2)) and (a > 0)

Op. Booléen (not) : if (not ((a + 8) > (b * 2))) and (a > 0)

Le - prioritaire  : if ((not ((a + 8) > (b * 2))) and (a > 0))

5 - 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 ?

5.1 Instruction conditionnelle : condition non booléenne

Cas d'une expression booléenne

Lorsque l'interpréteur Python lit un if ou un elif, il s'attend à trouver une expression booléenne derrière.

Exemple : if a >= 0:

Ici, l'expression est bien une expression booléenne.

Cas d'une expression non booléenne

Il peut arriver par contre que l'expression fournie ne soit pas une expression booléenne.

Exemple : if a:

Python ne va alors pas s'embêter : il va chercher à l'interpréter comme un booléen, comme si vous aviez tapé ceci :

Exemple : if bool(a):

Ainsi :

  • Si a est 0 ou 0.0 ou "" ou [] ou () ou {} ou None, a sera équivalent à un False.
  • Dans tous les autres cas, a sera équivalent à True.

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
def alors(n): reponse = 10 if n: reponse = 20 return reponse r1 = alors(45) r2 = alors("") r3 = alors("bonjour') r4 = alors([])

...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.

5.2 Instruction conditionnelle : tableau vide

On peut agir en fonction de l'état vide ou pas d'un type structuré en utilisant une simple instruction conditionnelle sur la variable référençant votre structure.

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
if tab: # si tab n'est pas vide (tab évalué à True) actions_si_le_tableau_n_est_pas_vide else: # sinon, c'est que tab est vide actions_si_le_tableau_est_vide

En utilisant not, on peut bien entendu mettre en avant que le tableau n'est pas vide :

1 2 3 4 5
if not tab: # tab est vide (car tab évalué à False, not tab à True) actions_si_le_tableau_est_vide else: # sinon, c'est que tab est vide actions_si_le_tableau_est_vide

CONCLUSION :

Si t fait référence à un type structuré :

  • if t     se traduit par "Si t n'est pas vide".
  • if not t se traduit par "Si t est vide".

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
# Déclaration des fonctions def reste_une_table_vide(tables:list) -> bool: """Prédicat qui renvoie True s'il reste une table non reservée""" for i in range(len(tables)): # pour chaque indice possible dans le tableau if not tables[i]: # si la table i est vide return True return False def trouver_une_table(tables:list) -> int: """Renvoie l'indice de la première table non réservée""" for i in range(len(tables)): # pour chaque indice possible dans le tableau if not tables[i]: # si la table i est vide return i # Instructions du programme principal reservations = ['Alice', '', 'Bob', '', '', 'Charlie'] if reste_une_table_vide(reservations): numero = trouver_une_table(reservations)

Le programme commence en ligne 21, le reste étant de la déclaration de fonctions.

21 22 23 24
reservations = ['Alice', '', 'Bob', '', '', 'Charlie'] if reste_une_table_vide(reservations): numero = trouver_une_table(reservations)

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 si facile que cela lorsqu'on vient de découvrir ces notions.

5.3 Instruction conditionnelle : une erreur typique

Voici une erreur que tout le monde va faire un jour ou l'autre, et qui nécessite pas mal des connaissances que vous avez vu aujourd'hui pour la comprendre.

Imaginions qu'on veuille vérifier que deux notes soient bien supérieures à 10 : en français, nous dirions que note1 et note2 sont supérieures à 10.

La faute courante

La mauvaise et fausse façon de traduire cela :

1
return note1 and note2 > 10

Et voilà sans doute une belle erreur sémantique. Pourquoi est-ce que cela ne fonctionne pas comme vous le voulez ?

  1. D'abord car les opérateurs de comparaison sont plus prioritaires que les opérateurs logiques. En réalité, vous avez écrit ceci :
  2. 1
    return note1 and (note2 > 10)
  3. L'opérateur and travaille donc sur les deux propositions suivantes :
    1. note1
    2. note2 > 10
  4. La première propriété étant juste note1, elle revient donc à demander si note1 contient quelque chose puisqu'elle sera évaluée à VRAI si note1 n'est ni vide ni nulle.

La traduction qui fait Python de cette ligne est donc : est-ce que note1 contient quelque chose et est-ce que note2 est supérieure à 10.

Cela n'est donc pas ce que nous voulions au départ...

La bonne façon de traduire ceci en Python

Nous n'avons pas le choix. Il faut parler à Python comme il le désire : il faut donc placer une propriété à gauche du and et une propriété à droite du and.

1
return note1 > 10 and note2 > 10

Puisqu'on sait que les opérateurs de comparaison sont prioritaires sur les opérateurs logiques, c'est comme si nous avions placé les parenthèses suivantes :

1
return (note1 > 10) and (note2 > 10)

On voit bien que cela veut bien dire ce qu'on voulait au départ : est-ce que note1 est supérieure à 10 et est-ce que note2 est supérieure à 10.

Bien entendu, en français, on évitera la répétition de la propriété car nous avons un cerveau. Ce qui n'est pas le cas de votre interpréteur Python. A vous de vous plier à son niveau de compréhension.

6 - FAQ

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

7 -

Maintenant que vous avez vu ou revu les notions d'instructions conditionnelles et de boucles bornées, voyons comment on peut les utiliser pour réaliser des choses plus concrêtes qu'un simple calcul.

Activité publiée le 01 11 2020
Dernière modification : 20 07 2023
Auteur : ows. h.