python lire

Identification

Infoforall

13 - Interface Console


Le disposif qui permet de faire interagir un humain et un système informatique se nomme une interface.

Nous avons déjà pas mal travaillé avec l'interface graphique Turtle :

Nous allons présenter aujourd'hui un peu plus l'interface texte Console et les deux fonctions natives que propose Python pour gérer une interface texte :

  1. print pour afficher sur l'écran et
  2. input pour récupérer le texte tapé sur le clavier.

Nous allons également revoir la différence entre fonctions d'interface et fonctions gérant les données.

Logiciel nécessaire pour l'activité : Thonny

Evaluation ✎ : questions 02-03-14-15

Résumé : Version HTML ou fond blanc ou ou PDF (couleur ou gris)

1 - Afficher à destination d'un humain sur la console

Nous avons déjà vu comment afficher des choses sur la console.

Il faut utiliser la fonction native print.

Nous avons vu que cette fonction native n'a rien à voir avec le mot-clé return des fonctions :

le mot-clé return

Le mot-clé return provoque la réponse immédiate de la fonction. Son but ? RENVOYER une réponse au PROGRAMME qui avait demandé à la fonction ce travail. Il s'agit donc d'une donnée informatique (même si c'est juste None) que le système informatique pourra stocker dans une variable.

1 2
def repondre(reponse): return reponse * 2

Si on utilise cette fonction en lui fournissant "Bon", que se passe-t-il sur la console ?

Réponse : ça dépend !

Cas 1 : Appel console avec stockage dans une variable

Regardons ce qui se passe si on stocke la réponse dans une variable.

>>> rep = repondre("Bon")

Moralité : aucun affichage. Par contre, la variable rep contient maintenant une information : la réponse de la fonction, à savoir le string "BonBon".

>>> rep 'BonBon'

Cas 2 : Appel console sans stockage dans une variable

>>> repondre("Bon") 'BonBon'

Cette fois, la réponse s'affiche dans la console après évaluation. Pourquoi ? Parce que. Parce que le concepteur de la console Python en a décidé ainsi : si un utilisateur tape une telle instruction-évaluation dans la console, on considère qu'à priori il veut la réponse ! Toute instruction se résumant à une évaluation est affichée dans la console Python.

C'est comme ça et c'est pratique.

Cas 3 : Appel dans un programme avec stockage dans une variable

Regardons ce qui se passe si on stocke la réponse dans une variable.

1 2 3 4
def repondre(reponse): return reponse * 2 rep = repondre("Bon")

Moralité : aucun affichage. Par contre, la variable rep contient maintenant une information : la réponse de la fonction, à savoir le string "BonBon".

>>> rep 'BonBon'

Cas 4 : Appel dans un programme sans stockage dans une variable

1 2 3 4
def repondre(reponse): return reponse * 2 repondre("Bon")

Aucun affichage, contrairement au cas console, on n'affiche rien par défaut lorsqu'une instruction dans un programme est juste une évaluation.

Pourquoi ? Parce que. C'est le comportement décidé : dans un programme, l'affichage est une décision volontaire.

Du coup, comment afficher des résultats à destination d'un humain dans la console ? Réponse : il faut forcer l'affichage avec la fonction native print.

La fonction native print

La fonction native print ne renvoie rien vers le programme, même pas None. Son but ? AFFICHER dans l'interface de sortie un message à destination d'un UTILISATEUR HUMAIN. Le système informatique ne pourra donc rien stocker en mémoire à priori : le message ne lui ai pas destiné.

Retenez bien ceci : le print ne renvoie rien ! N'utilisez jamais un print si on vous demande de renvoyer une réponse.

Il s'agit juste d'une fonction native permettant d'interagir avec l'UTILISATEUR en lui permettant de visualiser quelque chose du comportement interne de l'ordinateur.

01° On demande à quelqu'un de réaliser une fonction qui renvoie 10 fois l'argument qu'on lui transmet.

Quelle est la réponse correcte à fournir ? Quelle est la version qu'il ne fait surtout pas noter sur sa copie ?

1 2 3 4 5
def fois10A(entree): print(entree*10) def fois10B(entree): return entree*10

...CORRECTION...

La bonne réponse est la fonction fois10B puisqu'elle RENVOIE bien une réponse.

La fonction fois10B ne fait absolument pas le travail puisqu'elle ne fait qu'AFFICHER le résultat dans la console.

02° Utiliser le programme ci-dessous. Le programme provoque-t-il un affichage automatiquement ? Visualiser dans la console le contenu de la variable rep. Pourra-t-on réutiliser le "résultat" plus tard ?

1 2 3 4
def fois10B(entree): return entree*10 rep = fois10A("A")
>>> rep 'AAAAAAAAAA' >>> type(rep) ?

...CORRECTION...

Pas d'affichage automatique de la réponse mais elle est stockée.

Puisque la réponse est stockée dans une variable, on pourra réutiliser cette chaîne plus tard.

03° Utiliser le programme ci-dessous. Le programme provoque-t-il un affichage automatiquement ? Visualiser dans la console le contenu de la variable rep. Pourra-t-on réutiliser le "résultat" plus tard ?

1 2 3 4
def fois10A(entree): print(entree*10) rep = fois10A("A")
AAAAAAAAAA >>> rep >>> type(rep)

...CORRECTION...

Cette fois, c'est l'inverse : il y a un affichage automatique mais rien n'est stocké !

La fonction renvoie None et donc la variable ne contient ... rien.

Du coup, cette fonction ne sert à ... rien ?

On remarquera l'absence des guillemets sur l'affichage précédent : c'est normal : il est destiné à un humain. Il ne s'agit pas d'afficher le contenu réel de la variable mais juste en fournir une réprésentation. L'humain doit juste voir le message. Savoir que c'est un string, un interger ou un float n'a finalement aucune important pour lui.

04° On vous donne le code suivant.

1 2 3 4
def addition(a, b): return a + b reponse = addition(5, 10)

Que contient reponse ?

Quel énoncé d'exercice correspond à cette fonction 

  1. Créer une fonction qui renvoie la somme de a et de b
  2. Créer une fonction qui affiche la somme de a et de b

...CORRECTION...

La variable reponse contient la réponse de la fonction, à savoir la somme de 5 et 10, donc 15.

L'énoncé correct est donc réaliser une fonction qui renvoie la somme.

05° On vous donne le code suivant.

1 2 3 4
def addition(a, b): print(a + b) reponse = addition(5, 10)

Que contient reponse ?

Quel énoncé d'exercice correspond à cette fonction 

  1. Créer une fonction qui renvoie la somme de a et de b
  2. Créer une fonction qui affiche la somme de a et de b

...CORRECTION...

La variable reponse contient la réponse de la fonction, à savoir None !

C'est comme si on avait tapé ceci :

1 2 3 4 5
def addition(a, b): print(a + b) return None reponse = addition(5, 10)

L'énoncé correct est donc réaliser une fonction qui AFFICHE la somme. Il ne sert à rien ici de tenter de mémoriser la réponse : elle n'existe pas.

Fonctions d'interface machine-utilisateur

On nomme fonctions d'interface avec l'utilisateur les fonctions dont la tâche est d'interagir avec l'utilisateur à travers l'interface choisie : une interface graphique comme Turtle ou une interface texte comme la console.

Si on respecte le concept "une tâche = une fonction", une telle fonction ne doit pas réaliser de stockage de données puisque c'est déjà une tâche en soi.

On parle également de fonctions d'interaction.

Il existe donc deux types de fonctions d'interface utilisateur-machine :

  1. Celles qui permettent la communication dans le sens programme vers l'utilisateur
  2. Celles qui permettent la communication dans le sens utilisateur vers programme

Exemple basique 1 : fonction d'interface Console vers Utilisateur

1 2 3 4 5
def afficher(message): '''Affiche le message sur l'interface Console''' print(message) afficher("Bonjour !")

L'exécution de ce programme provoque l'affichage suivant :

Bonjour !

Pour fonctionner, cette fonction utilise la fonction native print mais la personne qui réalisera le programme n'a pas à s'en préoccuper : elle doit juste savoir qu'elle doit activer la fonction afficher.

Exemple basique 2 : fonction d'interface Turtle vers Utilisateur

1 2 3 4 5 6 7 8
import turtle as trt def afficher(message, reference): '''Affiche le message sur l'application graphique Turtle''' reference.write(message) crayon = trt.Turtle() afficher("Bonjour !", crayon)

L'utilisateur du programme précédent permet d'obtenir l'affichage suivant :

Pour fonctionner, cette fonction utilise la méthode write mais la personne qui réalisera le programme n'a pas à s'en préoccuper : elle doit juste savoir qu'elle doit activer la fonction afficher.

L'avantage des fonctions d'interface est donc qu'on n'a pas besoin de connaître les détails de l'interface sur laquelle on veut voir les choses s'afficher : on isole les particularités de cette interface d'affichage dans des fonctions bien spécifiques. Du coup, si on change d'interface, il suffira de modifier le code des fonctions d'interface mais le reste du programme devra toujours être le même !

Exemple basique 3 : prototype ou mode debug

Par contre, si vous voulez juste concevoir rapidement un petit programme sur la console, inutile de faire appel à une fonction d'affichage : vous avez le droit d'utiliser print directement !

1
print("Bonjour !")

06° Bien entendu, on peut utiiser une fonction qui renvoie une réponse et afficher ENSUITE sa réponse via un programme : il faut simplement demander poliment.

1 2 3 4 5
def fois10B(entree): return entree*10 rep = fois10B("A") print(rep)
Sur quelle ligne force-t-on l'affichage de la réponse dans la console ?

...CORRECTION...

Sur la ligne 5 : celle avec la fonction native print.

07° Peut-on dire que la fonction fois10B précédente est une fonction d'interface ?

...CORRECTION...

Non ! C'est une fonction qui réalise une tâche qui n'a rien à voir avec la communication avec l'utilisateur.

08°Quelqu'un propose de réaliser ceci. La fonction est opérationnelle, aucun problème. Mais quel est le problème ?

1 2 3 4
def fois10B(entree): reponse = entree*10 print(reponse) return reponse

...CORRECTION...

Cette fonction n'est pas "acceptable" car elle sert à exécuter deux choses :

  1. Une tâche consistant à réaliser un calcul sur les données et à fournir la réponse
  2. Une tâche consistant à afficher sur l'Interface
Une fonction, une tâche

Dans l'activité Une Fonction Une Tâche, nous avions vu que lorsqu'on réalise un code en tentant de le rendre le plus propre possible, on doit donc s'évertuer à :

  1. Encapsuler chaque tâche dans une fonction
  2. Réaliser les tâches complexes en faisant appel à des fonctions réalisant des tâches basiques

Nous pouvons donc rajouter que, lorsqu'on veut réaliser le code le plus propre possible, on doit créer des fonctions qui n'appartiennent

  1. soit à la catégorie des fonctions d'interface : elles permettent de communiquer avec l'utilisateur ou gère l'interface (graphique) mais ne modifie pas les données du programme en lui-même
  2. soit à la catégorie des fonctions gérant les données (calcul et stockage) mais elles n'interagissent pas directement avec l'utilisateur.

La fonction native print permet donc de créer une communication ORDINATEUR vers UTILISATEUR.

Nous avons revu comment forcer un AFFICHAGE.

Il est temps de voir comment permettre la communication UTILISATEUR vers ORDINATEUR dans le cas de l'interface CONSOLE.

2 - Lire les entrées clavier

Nous avons vu comment gérer cette communication avec TURTLE et sa programmation événementielle : il fallait utiliser les méthodes onclick pour permettre au programme de recevoir les informations de la souris et onkey pour recevoir les informations du clavier.

Nous allons voir qu'on peut écouter le clavier lorsqu'on utilise l'interface CONSOLE.

Pour cela, il faudra utiliser la fonction native input.

fonction native input

Il s'agit de la fonction d'interface Console permettant la communication Utilisateur vers Programme.

Cette fonction réalise trois choses :

  1. Elle affiche sur la console le string qu'on lui passe en paramètre : cela permet de poser une question.
  2. Elle bloque le programme en attendant que l'utilisateur tape quelque chose sur le clavier et valide la saisie en tapant sur ENTREE
  3. Elle répond en renvoyant au programme sous forme d'un string ce que l'utilisateur vient de taper sur le clavier.

09° Faire des essais dans la console Python tel que présenté ci-dessous.

Questions

  1. Que fait le programme en attendant la réponse de l'utilisateur ?
  2. Que renvoie la fonction input ?
  3. A quoi voit-on que la réponse de l'utilisateur est toujours fournie sous forme d'un string ?
>>> input("Quel est votre prénom ? ")

On pourrait alors taper quelque chose. Ci-desssous, le résultat si on tape Alice puis ENTREE.

>>> input("Quel est votre prénom ? ") Quel est votre prénom ? Alice 'Alice'

...CORRECTION...

Le programme est bloqué en attendant la réponse de l'utilisateur. La fonction input ne permet donc pas de faire de la programmation événementielle : nous sommes obligé de suivre le déroulement du programme dans l'ordre imposé par le code.

On remarque que la fonction native input renvoie ce qu'on vient de taper sous forme d'un string : la réponse sur la console est entourée de guillemets.

10° Que va contenir la variable reponse si l'utisateur tape Bob+ENTREE sur le clavier ? Vérifier en évaluant la variable dans la console.

>>> reponse = input("Quel est votre prénom ? ") Quel est votre prénom ? Bob

...CORRECTION...

La variable reponse va contenir la réponse de la fonction native input, à savoir un string 'Bob'.

>>> reponse = input("Quel est votre prénom ? ") Quel est votre prénom ? Bob >>> reponse 'Bob'

10° Sans lancer réellement le programme, dire ce que devrait afficher Python si on dit qu'on a 5 à gauche et 10 à droite ?

1 2 3 4 5 6
gauche = input("Combien d'argent dans la poche Gauche ? ") droite = input("Combien d'argent dans la poche Droite ? ") total = gauche + droite print(f"Au total, vous avez {total} euros.")
Combien d'argent dans la poche Gauche ? 5 Combien d'argent dans la poche Droite ? 10 Au total, vous avez ??? euros.

...CORRECTION...

Combien d'argent dans la poche Gauche ? 5 Combien d'argent dans la poche Droite ? 10 Au total, vous avez 510 euros.
Rappel : concaténation

On retrouve l'"addition" de strings, ce qu'on nomme la concaténation.

Puisque les réponses récupérées par un input sont toujours des strings, on concaténe le string '5' et le string '10', ce qui donne '510' :

>>> '5' + '10' '510' >>> 'Bon' + 'bon' 'Bonbon' >>> 5 + 10 15

Sur le dernier exemple, on voit que l'addition des deux entiers donne bien un entier.

Si on veut parvenir à additionner, il faut donc parvenir à convertir des strings en entiers. Pour cela, il faut simplement utiliser la fonction native int qui tente de convertir si c'est possible. Attention, si l'utilisateur tape quelque chose de non interprétable en entier, ça provoquera une erreur.

11° Lancer ce nouveau programme qui demande des choses à l'utilisateur ET convertit les réponses en entier. Est-ce que cela marche mieux ? Sur quelle(s) ligne(s) convertit-on les réponses en entiers ?

1 2 3 4 5 6 7 8 9
gauche = input("Combien d'argent dans la poche Gauche ? ") gauche = int(gauche) droite = input("Combien d'argent dans la poche Droite ? ") droite = int(droite) total = gauche + droite print(f"Au total, vous avez {total} euros.")
Combien d'argent dans la poche Gauche ? 5 Combien d'argent dans la poche Droite ? 10 Au total, vous avez ??? euros.

...CORRECTION...

Combien d'argent dans la poche Gauche ? 5 Combien d'argent dans la poche Droite ? 10 Au total, vous avez 15 euros.

C'est beaucoup mieux. La conversion se fait sur les lignes 2 et 5.

12° Modifier le programme pour qu'il sache gérer les centimes et donc les nombres à virgule.

...CORRECTION...

Il suffit d'utiliser la fonction de conversion float plutôt que la fonction de conversion float.

13° Expliquer étape par étape ce qui se passe ligne 1 si on rentre la valeur 5 ?

1 2 3 4 5 6
gauche = int(input("Combien d'argent dans la poche Gauche ? ")) droite = int(input("Combien d'argent dans la poche Droite ? ")) total = gauche + droite print(f"Au total, vous avez {total} euros.")
Combien d'argent dans la poche Gauche ? 5 Combien d'argent dans la poche Droite ? 10 Au total, vous avez ??? euros.

...CORRECTION...

Il faut revenir à la notion d'évaluation séquentielle.

L'interpréteur commence par exécuter la demande d'utilisation de input.

gauche = int(input("Combien d'argent dans la poche Gauche ? "))

On obtient donc ceci :

gauche = int('5')

Il reste à appliquer la fonction native int :

gauche = int('5')

Ce qui donne ceci :

gauche = 5

On peut donc affecter la variable gauche a la valeur 5.

Erreur courante

On arrive souvent à ce type d'erreur lorsqu'on oublie de convertir une partie des réponses uniquement :

>>> 5 + '10' TypeError: unsupported operand type(s) for +: 'int' and 'str'

La réponse de l'interpréteur Python est clair : il ne sait pas additionner ou concaténer des entiers avec des strings.

Comme vous pouvez le voir, nous utilisons simplement la fonction native input. Voyons comment nous pourrions l'encapsuler dans une fonction d'interface de façon à pouvoir plus facilement modifier notre programme en cas de changement d'interface.

Si on liste les tâches à faire :

  1. Il nous faut une fonction d'interface recuperer_un_entier qui renvoie la valeur entiere transmise par l'utilisateur.
  2. Une fonction de gestion de données trouver_le_total qui renvoie la somme de deux entiers.
  3. Une fonction d'interface afficher qui permet d'afficher un résultat destiné à l'utilisateur humain.

Voici le programme en version prototype rapide de travail

1 2 3 4 5 6
gauche = int(input("Combien d'argent dans la poche Gauche ? ")) droite = int(input("Combien d'argent dans la poche Droite ? ")) total = gauche + droite print(f"Au total, vous avez {total} euros.")

Voici le même programme en respectant la séparation des tâches dans des fonctions et la séparation claire entre fonction d'interface et fonction de gestion de données.

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
# Partie déclaration des fonctions d'interface def recuperer_un_entier(question): '''Récupère et renvoie un entier fourni par l'utilisateur''' reponse = int(input(question)) return reponse def afficher(message): '''Transmet un message à l'utilisateur''' print(message) # Partie déclaration des fonctions gérant les données def additionner(a, b): '''Renvoie la somme des deux entiers''' return a + b # Programme gauche = recuperer_un_entier("Combien d'argent dans la poche Gauche ? ") droite = recuperer_un_entier("Combien d'argent dans la poche Droite ? ") total = additionner(gauche, droite) afficher(f"Au total, vous avez {total} euros.")

14° Tester le second programme pour vérifier qu'il fonctionne correctement.

15° Le code du prototype est clairement plus concis que le second programme. Néanmoins si on décide de changer d'interface de communication, doit-on lire et modifier tout le code dans le premier programme ? Doit-on lire et modifier tout le code dans le second programme ?

...CORRECTION...

Si on veut changer d'interface, il faut relire tout le code du premier programme...

Par contre, dans le second programme, on pourra se limiter à modifier les fonctions d'interface !

La séparation Interface / Données peut paraître un peu artificiel sur un projet de 10 lignes, mais je vous assure qu'avec 30 000 lignes de code, on est bien content d'avoir séparer gestion de l'interface et gestion des données !

3 - Erreurs courantes avec les prints et les inputs

Voici deux erreurs "courantes" qu'il ne faudra jamais faire vous-même.

Petite erreur : erreur d'encapsulation

On voit assez souvent des fonctions qui gèrent à la fois l'interface ET les données.

1 2 3 4 5 6 7 8 9
# NE PAS REPRODUIRE CELA si possible def verifier_mot_de_passe(mot_de_passe): '''Renvoie True si l'utilisateur tape le bon mot de passe''' reponse = input("Rentrez votre mot de passe svp : ") if reponse == mot_de_passe : print("Cool. C'est bien vous !") return True print("Nan. Même pas en rêve !") return False

Ici, c'est acceptable si le but est juste de faire un prototype rapide mais on voit clairement que notre fonction fait à la fois de l'interaction avec l'utilisateur et de la gestion des données. On voit du print mélanger avec du return par exemple.

Voici une solution où on ne mélange pas les deux types d'action. La partie liaison regroupe les fonctions qui vont appel aux fonctions d'interface et aux fontions de gestion de données.

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
# Partie déclaration des fonctions d'interface def recuperer_clavier(question): '''Renvoie la réponse utilisateur''' return input(question) def afficher(message): '''Fournit un message à l'utilisateur''' print(message) # Partie déclaration des fonctions gestion de données def comparer(mot_de_passe, proposition): '''Renvoie True si les deux mots de passe sont les mêmes''' return mot_de_passe == proposition def message_a_transmettre(resultat): if resultat : return "Cool. C'est bien vous !" return "Nan. Même pas en rêve !" # Partie déclaration de la fonction de liaison entre interface et données def verifier_mot_de_passe(mot_de_passe): '''Renvoie True si l'utilisateur tape le bon mot de passe''' prop = recuperer_clavier("Rentrez votre mot de passe svp : ") rep = comparer(mot_de_passe, prop) afficher(message_a_transmettre(rep)) return rep # Programme verifier_mot_de_passe("1234")

C'est plus propre, mais on passe de 9 lignes à 35 !

Dans le cadre d'un petit projet maison, pas d'inquiétude, la solution 1 est donc acceptée quand même. Par contre, il faut savoir que ce n'est pas propre : en cas de changement d'interface, il faut falloir relire tout le code pour savoir ce qu'on peut récupérer ou pas.

Vous allez voir en cours d'année que je ne cherche pas non plus à garantir la séparation interface / gestion dans toutes les activités.

L'important : savoir qu'on devrait le faire sur un vrai gros projet.

L'erreur suivante est par contre une vraie grosse erreur qui vous garantit des points en moins sur vos copies ! Le code suivant est vraiment un code abominable.

Grossière erreur à ne jamais reproduire. Jamais. Never.

Lorsqu'on utilise une fonction, on lui transmet les données à traiter via les paramètres de réception.

Exemple avec la fonction addition :

1 2 3 4
# FONCTION CORRECTE def addition(a, b): somme = a + b return somme

Si on veut additionner 5 et 10, on lance l'appel suivant :

>>> addition(5, 10) 15

On voit parfois une version limite de ce style de fonction :

1 2 3 4 5 6
# NE PAS REPRODUIRE : on mélange INTERFACE et GESTION de DONNEES def addition(): a = int(input("Premier nombre : ")) b = int(input("Second nombre : ")) somme = a + b return somme

Ce code n'est vraiment pas top :

  1. On mélange interface et données
  2. On ne peut pas imposer des valeurs pour faire des vérifications automatiques : il faut que quelqu'un tape les entrées !

Nous arrivons maintenant au vrai cas abominable en terme de compréhension des fonctions :

1 2 3 4 5 6
# ABOMINABLE -- NE PAS REPRODUIRE -- VRAIMENT def addition(a, b): a = int(input("Premier nombre : ")) # on écrase le paramètre a ! b = int(input("Second nombre : ")) # on écrase le paramètre b ! somme = a + b return somme

Comme vous le voyez, produire ce type de code montre clairement que le concepteur n'a pas compris que les paramètres a et b sont des valeurs qu'on transmet à la fonction pour qu'elle les gère justement.

Voilà pourquoi il faudra toujours être vigilant si vous voulez créer un programme autonome qui gère des communications de l'utilisateur.

4 - Exemple de jeu autonome

Il existe en réalité deux façons de réaliser une "application" avec Python :

  1. Faire un programme autonome sur lequel l'utilisateur n'a pas la main : il est obligé de faire exactement ce qu'on veut de lui. Pratique pour faire un "jeu" pour quelqu'un qui n'y connait rien en informatique. Il suffit de taper les réponses.
  2. Utiliser le mode interactif de Python (avec Thonny par exemple) en créant des fonctions qu'on place en mémoire puis en faisant l'appel à ces fonctions directement depuis la console Python de Thonny. Cela nécessite de s'y connaitre un peu en informatique.

Voici par exemple un jeu AUTONOME où on demande à l'utilisateur des additions et qui compte les points.

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
# Importation import random as rd # Fonctions d'interface def recuperer_entier(message): '''Renvoie l'entier fourni par l'utilisateur''' return int(input(message)) def afficher(message): print(message) # Fonctions de gestion de données def question(n1, n2): '''Renvoie la question à afficher''' return f"Que vaut {n1} + {n2} ? " def resultat(reponse): '''Renvoie la réponse à afficher''' if reponse : return f"Bravo !" return "Votre réponse est fausse" def final(nbr_b, nbr_f): '''Renvoie le message de fin''' return f"Vous avez eu {nbr_b} bonnes réponses sur {nbr_b + nbr_f}" def verifier(n, n1, n2): '''Renvoie True si la réponse est bonne''' return n == (n1 + n2) def aleatoire(): return rd.randint(1,10) # Fonctions de liaison def jouer(): '''On joue tant que l'utilisateur n'a pas fourni 5 bonnes réponses''' nbr_bonnes = 0 nbr_fausses = 0 while nbr_bonnes < 5 : n1 = aleatoire() n2 = aleatoire() n = recuperer_entier(question(n1,n2)) bon = verifier(n, n1, n2) if bon : nbr_bonnes = nbr_bonnes + 1 else : nbr_fausses = nbr_fausses + 1 afficher(resultat(bon)) afficher(final(nbr_bonnes, nbr_fausses)) # Programme jouer()

16° Utiliser cette version du jeu en jouant une partie ou deux. Vérifier que vous comprennez le cheminement du programme en lui-même.

Il nous manque encore quelques notions sur l'interaction entre les variables globales du programme et les fonctions pour vous proposer l'équivalent en mode interactif directement depuis Thonny. Mais vous activez les fonctions depuis la console depuis assez longtemps maintenant pour comprendre qu'on pourrait très bien se passer de print et input et ne travailler qu'avec des fonctions :

  1. L'utilisateur peut fournir des valeurs aux fonctions à travers les arguments qu'il envoie
  2. L'utilisateur peut interroger le contenu des variables directement depuis la console

5 - FAQ

Quand l'utilisateur tape une lettre cela provoque une erreur ! On peut faire quelque chose ?

C'est bien le problème des informations qui proviennent d'un humain. Il a tendance à répondre n'importe quoi.

Je ne peux pas vous fournir de solution utilisant uniquement des notions déjà abordées.

Si on résume : on tente toujours de créer des programmes en séparant les fonctions en trois catégories :

  1. Les fonctions d'interface qui agissent avec l'utilisateur (récupération des réponses de l'utilisateur et affichage des réponses du programme)
  2. Les fonctions gérant les données qui ne vont que travailler sur les données : calcul et stockage
  3. Les fonctions de liaison qui gèrent les deux catégories de fonctions précédentes. C'est typiquement dans ces fonctions que se trouve le coeur du programme : elles réalisent des tâches complexes en faisant appel à d'autres fonctions plus spécialisées.

Et en conclusion : à moins que vous ne soyez en train de réaliser une vraie interface autonome en projet NSI, n'utilisez pas de input et comprennez bien qu'un print ne doit jamais remplacer un return dans une fonction !

Les fonctions natives print et input sont des fonctions d'interface implémentées de base qui ne doivent servir qu'à cela : gérer l'interaction avec l'utilisateur dans le cadre d'une application AUTONOME utilisant la CONSOLE en tant qu'INTERFACE HOMME-MACHINE.

Activité publiée le 28 08 2019
Dernière modification : 15 11 2020
Auteur : ows. h.