Script et programme

Identification

Infoforall

7 - Créer un programme en Python


Aujourd'hui, nous allons voir qu'un programme doit être organisé d'une certaine façon

Lors de l'activité, on vous montrera plusieurs applications automatisées qu'on peut réaliser via un programme Python.

Tracer un graphique :

Récupérer une image, la transformer plusieurs fois et coller l'ensemble pour faire une belle affiche :

Logiciel nécessaire pour l'activité : Thonny

Evaluation : 6 questions

  questions 05-06-10-13

  questions 03-14

DM 🏠 : Non

Documents de cours PDF : .PDF

Sources latex : .TEX et entete.tex et licence.tex

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

1 - Cours : structure et exécution d'un programme

Attention aux noms des programmes Python

Vous allez enregistrer votre programme en lui donnant un nom. N'utilisez JAMAIS le nom d'un des modules Python qui existent déjà : turtle, random... Sinon, vous ne pourriez plus utiliser turtle.

1.1 Différence entre console interactive et programme

Cas de la console

Lorsqu'une ligne contient uniquement une expression, l'interpréteur l'évalue et affiche le résultat.

>>> a = 10 >>> b = a + 2 >>> b 12

On visualise bien que 12 s'affiche sur la console lorsqu'on demande juste d'évaluer b.

Cas du programme

Lorsqu'une ligne contient uniquement une expression, l'interpréteur l'évalue et... c'est tout. Pas d'affichage.

1 2 3
a = 10 b = a + 2 b

Ce programme n'affiche rien alors que la ligne 3 ne contient que la demande d'évaluation d'une expresssion.

Dans un programme, si vous voulez voir quelque chose s'afficher, il faut le demander explicitement :

1 2 3
a = 10 b = a + 2 print(b)
1.2 COMMENTAIRES : expliquer le fonctionnement

Les commentaires sont destinés à un lecteur humain et ils visent à rendre le code interne facile à comprendre.

Cela doit permettre de modifier un code même plusieurs années après sa création initiale.

Pour rajouter un commentaire en Python, on utilise le caractère dièse (#) de façon adaptée. Trois exemples à parfaitement comprendre :

  • Commentaire sur toute une ligne (ligne 1 ci-dessous)
  • 1
    # Toute cette ligne est un commentaire.
  • Commentaire en fin de ligne (ligne 2 ci-dessous)
  • 2
    print("Bonjour tout le monde") # Ceci est également un commentaire
  • Notez bien que la ligne 3 ne comporte aucun commentaire puisque le # fait juste partie d'un string.
  • 3
    print("Cette ligne ne contient pas de # commentaire")

Voici le résultat de ce programme L1 à L3 dans la console : il n'affiche pas les commentaires.

1 2 3
# Toute cette ligne est un commentaire. print("Bonjour tout le monde") # Ceci est également un commentaire print("Cette ligne ne contient pas de # commentaire")
>>> %Run progcommentaires.py Bonjour tout le monde Cette ligne ne contient pas de # commentaire >>>

L'interpréteur Python ne tentera pas d'exécuter les commentaires.

1.3 Structure d'un programme

Voici la structure attendue d'un programme Python :

  1. Importation des modules nécessaires au programme.
  2. Déclarations des CONSTANTES : par convention, le nom des CONSTANTES est constitué uniquement de majuscules.
  3. Déclaration des variables globales destinées à être lues depuis des fonctions : à utiliser avec modération. Elles sont sources de nombreux disfonctionnements lorsqu'elles sont mal gérées.
  4. Déclaration des fonctions.
  5. Les instructions du programme en lui-même : on nomme cette partie "programme principal" parfois. On y place également les variables globales qu'on envoie simplement en tant que paramètres.

Convention

Habituellement, on sépare les parties ci-dessous par au moins deux lignes vides.

1.4 Noms des variables globales et locales

Deux utilisations des variables globales :

A - Lues directement par les fonctions

Cela semble pratique mais si vous décidez de changer le nom dans le programme, c'est l'ensemble des lignes de vos fonctions qu'il va falloir modifier. C'est donc une source d'erreurs.

Exemple avec une fonction qui déplace le crayon pour le déplacer à la position voulue :

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
# Importation des modules supplémentaires import turtle as trt # CONSTANTES et variables globales lues par les fonctions feutre = trt.Turtle() # feutre va être lue par les fonctions # Déclaration des fonctions def deplacer(x, y): feutre.penup() # On lève la pointe feutre.goto(x, y) # On déplace le crayon feutre.pendown() # On abaisse la pointe # Programme feutre.color("red") feutre.fillcolor("orange") feutre.pensize(4) feutre.speed(5) feutre.forward(150) deplacer(0, 100) feutre.forward(150) deplacer(0, -100) feutre.forward(150)
B - Transmises aux fonctions lors de l'appel

Avantage : le nom de la variable globale n'a aucune importance depus la fonction puisqu'on la stocke temporairement dans une variable locale. Changer le nom de la variable d'un côté ou de l'autre n'aura donc aucune incidence.

Désavantage : le code semble plus lourd.

D'ailleurs, on peut même garder le même nom si on veut, Python ne sera pas perdu entre variable locale et globale.

Pour ne pas perdre le lecteur humain, le mieux est d'avoir

  • un nom pour la variable globale (feutre) et
  • un nom proche dans toutes les fonctions qui vont le récupérer en entrée (ftr).
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
# Importation des modules supplémentaires import turtle as trt # CONSTANTES et variables globales lues par les fonctions # Déclaration des fonctions def deplacer(ftr, x, y): ftr.penup() # On lève la pointe ftr.goto(x, y) # On déplace le crayon ftr.pendown() # On abaisse la pointe # Programme feutre = trt.Turtle() # transmise en entrée aux fonctions feutre.color("red") feutre.fillcolor("orange") feutre.pensize(4) feutre.speed(5) feutre.forward(150) deplacer(feutre, 0, 100) feutre.forward(150) deplacer(feutre, 0, -100) feutre.forward(150)

Avant de commencer l'activité, quelques rappels sur la façon de comprendre pourquoi l'interpréteur n'est pas content parfois :

Bug 01° Voici un programme qui provoque une erreur. Attention, contrairement à notre habitude en NSI, j'ai importé directement TOUT ce que contient le module turtle en utilisant le caractère magique * qui signifie "tout". C'est une mauvaise pratique en informatique car la plupart du temps, nous n'importons pas qu'un seul module à la fois. Par contre, l'avantage vient du fait que les programmes sont plus courts puisqu'on n'a pas besoin de préfixer chaque fonction par le nom du module qui le contient.

Questions

  • Que signifie le message d'erreur ?
  • A quoi est-ce dû ?
1 2 3 4 5 6 7 8 9 10
write("Origine", font=('Arial', 28, 'normal')) goto(0, 100) write("y > 0", font=('Arial', 28, 'normal')) from turtle import * goto(0, -100) write("y < 0", font=('Arial', 28, 'normal')) goto(300, 0) write("x > 0", font=('Arial', 28, 'normal')) goto(-300, 0) write("x < 0", font=('Arial', 28, 'normal'))
Traceback (most recent call last): File "/home/rv/axes.py", line 1, in <module>: write("Origine", font=('Arial', 28, 'normal')) NameError: name 'write' is not defined

...CORRECTION...

L'interpréteur signale qu'il y a un problème en ligne 1 : in ne connait pas le nom write.

C'est normal puisque ce nom de fonction est inclu dans le module turtle qui n'est importé qu'à partir de la ligne 4.

Bug 02° Ce programme provoque une erreur. L'interpréteur ne comprend pas ce qu'on lui demande.

  1. Sur quelle ligne se situe le problème ?
  2. Quel est le problème ?
1 2 3 4 5 6 7 8 9 10
from turtle import * write("Origine", font=('Arial', 28, 'normal')) goto(0, 100) write("y > 0", font=('Arial', 28, 'normal')) goto(0, -100) write("y < 0", font=('Arial', 28, 'normal')) goto(300, 0) write(x > 0, font=('Arial', 28, 'normal')) goto(-300, 0) write("x < 0", font=('Arial', 28, 'normal'))

...CORRECTION...

Traceback (most recent call last): File "/home/rv/axes.py", line 8, in <module>: write(x > 0, font=('Arial', 28, 'normal')) NameError: name 'x' is not defined

Le problème vient du fait qu'on doit transmettre un string et qu'on a "oublié" de placer les guillemets autour du texte à afficher.

Remarquez bien qu'il a exécuté le programme sur les lignes 1 à 7. Il stoppe à la 8.

Bug 03° Ce programme provoque une erreur. L'interpréteur ne comprend pas ce qu'on lui demande.

  1. Sur quelle ligne se situe le problème ?
  2. Quel est le problème ?
1 2 3 4 5 6 7 8 9 10
from turtle import * write("Origine", font=('Arial', 28, 'normal')) goto(0, 100} write("y > 0", font=('Arial', 28, 'normal')) goto(0, -100) write("y < 0", font=('Arial', 28, 'normal')) goto(300, 0) write("x > 0", font=('Arial', 28, 'normal')) goto(-300, 0) write("x < 0", font=('Arial', 28, 'normal'))

...CORRECTION...

Traceback (most recent call last): File "/home/rv/axes.py", line 3, in <module>: goto(0, 100} ^ SyntaxError: closing parenthesis '}' does not match opening parenthesis '('

Le problème vient du fait qu'on veut fermer les informations transmises à la fonction avec un accolade. Or, on doit utiliser une parenthèse. L'interpréteur Python signale donc qu'il ne comprend rien à ce qu'on désire. Par contre, il a exécuté le programme sur les lignes 1 et 2.

Moralité : avant d'appeler l'enseignant à l'aide parce que Python n'est pas content, commencez par lire le message d'erreur pour localiser le problème et tentez de voir sa nature. C'est ce que je fais quand je viens vous aider !

Cette activité (en deux parties) consiste en une présentation de programmes qu'on peut réaliser en réalisant des importations de modules divers et variés. Je donne quelques exemples mais le nombre de modules réalisés pour Python est énorme.

Aujourd'hui, on commence par l'Interface Homme Machine la plus basique possible : le terminal-texte.

2 - IHM console

On travaillera ici sur les strings, les dictionnaires et les interactions via la console.

Nous allons réaliser un petit jeu : on génère deux entiers au hasard et on demande à l'utilisateur de donner la valeur de leur multiplication. On compte les points et on donne le total à la fin.

Pour cela, nous allons avoir besoin de faire 3 compléments :

  1. sur print() qui affiche à l'écran
  2. sur input() qui récupère la saisie clavier
  3. sur le module random qui permet de générer des nombres aléatoires.
2.1 IHM Console

Le disposif qui permet de faire interagir deux systèmes sans que l'un et l'autre ne connaissent les détails de fonctionnement de l'autre se nomme une interface.

Lorsque l'interface se fait entre un homme et une machine, on la nomme IHM : Interface Homme Machine.

La console est l'une des IHM les plus simples puisque l'interaction peut se gérer avec deux fonctions depuis Python.

  1. PROGRAMME vers HUMAIN : print() pour afficher sur l'écran
  2. HUMAIN vers PROGRAMME : input() pour récupérer le texte tapé sur le clavier
2.2 print() pour afficher une variable depuis un programme

2.2.1 Affichage avec print()

La fonction native print() est une fonction d'Interface Homme Machine (IHM) qui affiche un contenu dans la console à destination d'un humain.

>>> a = "Salut à toi !" >>> a 'Salut à toi !' >>> print(a) Salut à toi !

On voit qu'avec print() le texte affiché n'est pas entouré de guillemets. Il s'agit d'un simple texte, un simple affichage.

Cette fonction agit dans le sens MACHINE vers HUMAIN.

2.2.2 Aucune mémoire avec print()

On ne mémorise pas l'information affichée lorsqu'on utilise print().

Exemple explicite : on récupére dans rep la réponse de la fonction print(). rep ne contient rien.

>>> a = "Reçu ?" >>> a 'Reçu ?' >>> rep = print(a) Reçu ? >>> rep >>>
2.2.3 Exemple de programme

Voici un programme qui affiche le contenu final de c :

1 2 3 4 5 6 7
print("Début du programme") a = 5 b = 10 c = a + b a = 100 # Attention ; ceci ne va pas modifier le c créé sur la ligne précédente print(c) print("Fin du programme")
>>> %Run acti_programme.py Début du programme 15 Fin du programme >>>
2.2.4 Que peut-on envoyer comme entrée à print() ?

Tout ce que vous voulez. C'est l'intérêt de la fonction, elle affiche.

2.2.5 Texte + Variable (plusieurs arguments)

Lorsqu'on veut afficher du texte et des variables, on peut envoyer plusieurs arguments (des strings et des variables) à la fonction, en les séparant par des virgules.

1 2 3 4 5 6 7
print("Début du programme") a = 5 b = 10 c = a + b print("Variable c : ", c) print("Fin du programme")
>>> %Run acti_programme.py Début du programme Variable c : 15 Fin du programme >>>
2.2.6 Texte + Variable (f-string)

Lorsqu'on veut afficher du texte et des variables, on peut plutôt utiliser un f-string. C'est un string :

  • Précédé d'un f avant le symbole d'ouverture.
  • Pouvant contenir des expressions entre accolades : elles seront évaluées et affichées.
1 2 3 4 5 6 7
print("Début du programme") a = 5 b = 10 c = a + b print(f"Variable c : {c}") print("Fin du programme")
>>> %Run acti_programme.py Début du programme Variable c : 15 Fin du programme >>>

01° Deux élèves proposent ces deux programmes qui se ressemblent beaucoup.

Le deuxième élève déclare que son programme est meilleur car il est plus court que le précédent et fait la même chose puisqu'il affiche la même chose.

Il se trompe... Expliquez pourquoi le programme 2 ne fait pas la même chose que le programme 1.

Programme 1

1 2 3 4
a = 5 b = 10 c = a + b print(c)

Programme 2

1 2 3
a = 5 b = 10 print(a + b)

...CORRECTION...

Le programme 2 ne fait pas la même chose : il ne mémorise pas le résultat de l'addition.

Il affiche simplement le résultat pour qu'un humain puisse le visualiser. Mais on ne pourra pas continuer à travailler avec ce résultat puisqu'il n'a pas été mémorisé dans une variable.

2.3 Un print() n'est pas un return

SUPER IMPORTANT

Si un énoncé signale : créer une fonction "qui renvoie" "qui calcule" ou mot similaire, il faut utiliser return. On pourra stocker la réponse dans une variable.

Si un énoncé signale : créer une fonction "qui affiche", il faut utiliser print() et il s'agit d'un simple message dans l'IHM, pas de mémorisation.

02° Deux fonctions à réaliser :

  • Réaliser une fonction addition()
    • qui attend deux nombres en entrée (on les stockera dans a et b et
    • qui renvoie la somme des deux nombres.
  • Réaliser une fonction affiche()
    • qui attend deux nombres en entrée (on les stockera dans a et b et
    • qui affiche la somme des deux nombres.

...CORRECTION...

1 2
def addition(a, b): return a + b

...CORRECTION...

1 2
def affiche(a, b): print(a + b)

Ou si on veut utiliser addition() :

1 2 3 4 5
def addition(a, b): return a + b def affiche(a, b): print(addition(a, b))
2.4 print() et caractères de contrôle

On pourrait croire que la fonction native print() n'a aucun intérêt lors de l'utilisation de la console interactive.

Exemple :

>>> a = "Salut à toi !" >>> a 'Salut à toi !' >>> print(a) Salut à toi !

Et bien, ce n'est pas vrai.

Il existe des caractères de contrôle (des caractères qui ne s'affichent pas mais provoquent un effet) : le passage à la ligne, la tabulation...

Pour provoquer l'effet voulu, il faut utiliser print().

2.4.1 Passage à la ligne

Pour passer à la ligne, on utilise deux glyphes \n : l'anti-slash \ et n ( n pour pour new line).

>>> texte = "Nom\nPrenom\nAge" >>> texte "Nom\nPrenom\nAge" >>> print(texte) Nom Prenom Age

Le passage à la ligne caractèrise un unique caractère, pas 2 :

>>> texte = "\n" >>> len(texte) 1

La fonction native ord() permet de récupérer le code ASCII correspondant.

>>> caractere = "\n" >>> code = ord(caractere) >>> code 10

La fonction native chr() permet de récupérer le caractère correspondant à un code.

>>> code = 10 >>> caractere = chr(code) >>> caractere '\n'
2.4.2 Tabulation

La tabulation \t décale le texte sur une position commune.

>>> a = "Nom\tPrenom\nAlice\tInborderlands\nBob\tLeponge" >>> a 'Nom\tPrenom\nAlice\tInborderlands\nBob\tLeponge' >>> print(a) Nom Prenom Alice Inborderlands Bob Leponge >>> len('\t') 1 >>> ord('\t') 9 >>> chr(9) '\t'
2.4.3 Caractère d'échappement

L'anti-slash est ce qu'on nomme un caractère d'échappement : il signale que le caractère suivant ne doit pas être traité comme un caractère normal : \t veut dire de créer une tabulation, pas d'afficher un anti-slash et un t.

Comment afficher un anti-slash alors ? C'est simple, on place deux anti-slashs à la suite. Le premire est le caractère d'échappement et le suivant indique de cet anti-slash ne doit pas être traité comme un caractère d'échappement mais comme un simple caractère.

>>> print("Voilà un antislash \\") Voilà un antislash \
2.4.4 Caractère Bell

Il s'agit du petit son de cloche signalant souvent un petit problème.

>>> son = chr(7) >>> print(son)

✌ 03-A° Réaliser un programme qui stocke dans 4 variables deux noms de série et les thèmes de chacune de ces séries. Ensuite, vous utiliserez 4 appels à print() pour afficher dans la console un message qui ressemble à cela :

Réalisation Thème ----------- ----- nomSerie1 thème1 nomSerie2 thème2

Attention, parfois il faut plusieurs tabulations \t de suite.

Consignes supplémentaires

Vous réalisez votre programme en utilisant print() en lui envoyant des arguments séparés par des virgules. Voir le rappel ci-dessous au besoin.

(Rappel) print() pour afficher une variable depuis un programme

(Rappel)..1 Affichage avec print()

La fonction native print() est une fonction d'Interface Homme Machine (IHM) qui affiche un contenu dans la console à destination d'un humain.

>>> a = "Salut à toi !" >>> a 'Salut à toi !' >>> print(a) Salut à toi !

On voit qu'avec print() le texte affiché n'est pas entouré de guillemets. Il s'agit d'un simple texte, un simple affichage.

Cette fonction agit dans le sens MACHINE vers HUMAIN.

(Rappel)..2 Aucune mémoire avec print()

On ne mémorise pas l'information affichée lorsqu'on utilise print().

Exemple explicite : on récupére dans rep la réponse de la fonction print(). rep ne contient rien.

>>> a = "Reçu ?" >>> a 'Reçu ?' >>> rep = print(a) Reçu ? >>> rep >>>
(Rappel)..3 Exemple de programme

Voici un programme qui affiche le contenu final de c :

1 2 3 4 5 6 7
print("Début du programme") a = 5 b = 10 c = a + b a = 100 # Attention ; ceci ne va pas modifier le c créé sur la ligne précédente print(c) print("Fin du programme")
>>> %Run acti_programme.py Début du programme 15 Fin du programme >>>
(Rappel)..4 Que peut-on envoyer comme entrée à print() ?

Tout ce que vous voulez. C'est l'intérêt de la fonction, elle affiche.

(Rappel)..5 Texte + Variable (plusieurs arguments)

Lorsqu'on veut afficher du texte et des variables, on peut envoyer plusieurs arguments (des strings et des variables) à la fonction, en les séparant par des virgules.

1 2 3 4 5 6 7
print("Début du programme") a = 5 b = 10 c = a + b print("Variable c : ", c) print("Fin du programme")
>>> %Run acti_programme.py Début du programme Variable c : 15 Fin du programme >>>
(Rappel)..6 Texte + Variable (f-string)

Lorsqu'on veut afficher du texte et des variables, on peut plutôt utiliser un f-string. C'est un string :

  • Précédé d'un f avant le symbole d'ouverture.
  • Pouvant contenir des expressions entre accolades : elles seront évaluées et affichées.
1 2 3 4 5 6 7
print("Début du programme") a = 5 b = 10 c = a + b print(f"Variable c : {c}") print("Fin du programme")
>>> %Run acti_programme.py Début du programme Variable c : 15 Fin du programme >>>

✌ 03-N° Réaliser un programme qui stocke dans 4 variables deux noms de série et les thèmes de chacune de ces séries. Ensuite, vous utiliserez 4 appels à print() pour afficher dans la console un message qui ressemble à cela :

Réalisation Thème ----------- ----- nomSerie1 thème1 nomSerie2 thème2

Attention, parfois il faut plusieurs tabulations \t de suite.

Consignes supplémentaires

Vous réalisez votre programme en utilisant print() en lui fournissant un f-string.


Passons maintenant à la récupération des données envoyées par l'utilisateur.

2.5 Fonction input() pour récupérer les entrées clavier

2.5.1 Principe fondamental

La fonction native input() récupère la réponse reçue au clavier sous forme d'un string. Pour valider la réponse, il faut appuyer sur entrée (sur l'exemple, on répond Bonjour).

>>> reponse = input() Bonjour >>> reponse 'Bonjour' >>> reponse * 3 'BonjourBonjourBonjour'

Le problème vient du fait que TOUT ce qu'on récupère depuis le clavier est interprété comme un string. D'où cette situation bizarre si on ne fait pas attention :

>>> note = input() 18 >>> note '18' >>> note * 2 '1818'
2.5.2 Récupérer un entier ou un flottant

Puisqu'on ne récupère que des strings, il faut simplement tenter de convertir le string reçu en integer, en utilisant la fonction native int().

>>> reponse = int(input()) 5 >>> reponse 5 >>> reponse * 3 15
>>> reponse = float(input()) 5 >>> reponse 5.0 >>> reponse * 3 15.0
2.5.3 Utilisation complète

Puisque input() permet de poser une question à l'utilisateur, on peut lui transmettre un string contenant la question voulue.

On peut ainsi taper ceci :
reponse = input("Veuillez fournir un nombre entier : ")

L'interpréteur Python va alloir faire trois choses

  1. Afficher votre message, comme si vous aviez utilisé un print() mais sans passage à la ligne automatique.
  2. Récupérer la réponse de l'utilisateur sous forme d'un string
  3. Placer ce string dans la variable reponse
>>> reponse = int(input("Veuillez fournir une note : ")) Veuillez fournir une note : 5 >>> reponse 5 >>> reponse * 3 15
Hors Programme  : et en cas d'impossibilité de conversion ?

Cela ne tombera pas le jour de l'examen ou dans un DS, mais c'est pratique et nous allons l'utiliser aujourd'hui. Rien à retenir, il suffit de voir un peu commment cela fonctionne.

Il est possible que le string récupéré ne soit pas interprétable en tant qu'entier. Dans ce cas, cela lève une exception :

>>> reponse = int(input("Veuillez fournir une note : ")) Veuillez fournir une note : cinq ValueError: invalid literal for int() with base 10: 'trois'

Le seul moyen de palier à ceci est d'utiliser quelques notions hors programme en NSI. Il s'agit de try except : si Python lève une exception pendant le bloc try, plutôt que d'interrompre brutalement le programme, il saute simplement dans le bloc except. On peut alors y gérer le problème.

1 2 3 4 5 6 7 8 9
def recuperer_une_note(): reponse = "" # "Fausse réponse" pour rentre dans le while while type(reponse) != int: # TQ reponse n'est pas un entier rep_clavier = input("Note : ") # récupère le choix de l'utilisateur try: # Essaye de faire ceci : reponse = int(rep_clavier) # transforme rep_clavier en int except: # Si cela déclenche une Exception pass # on ne fait rien, on passe... return reponse

Voici une utilisation possible en mode interactif (une fois la fonction mise en mémoire bien entendu)

>>> %Run portee.py >>> note = recuperer_une_note() Note : cinq Note : 5 >>> note 5

Exercices autour des mots de passe

04° Dans le script ci-dessous, la variable mdp_recu contient le mot de passe reçu et la variable mdp_reel contient le vrai mot de passe attendu. Pour cela, le plus simple est de montrer dans quel ordre l'interpréteur va exécuter cette ligne.

Questions :

  1. Sur quelle ligne se trouve l'instruction qui permet de récupérer l'entrée clavier ?
  2. quel est le type de l'expression mdp_recu == mdp_reel ?
  3. expliquer ce que contiendrait la variable autorisation si l'utilisateur avait tapé 1234 au clavier.
1 2 3 4
print("Entrez votre mot de passe :") mdp_recu = input() mdp_reel = "12345" autorisation = mdp_recu == mdp_reel

...CORRECTION...

  1. Sur quelle ligne se trouve l'instruction qui permet de récupérer l'entrée clavier ?
  2. Il s'agit de la ligne 2 avec input()

  3. quel est le type de l'expression mdp_recu == mdp_reel ?
  4. On utilise l'opérateur == qui permet de comparer le contenu des deux données transmises à gauche et à droite. Il va renvoyer un booléen.

  5. expliquer ce que contiendrait la variable autorisation si l'utilisateur avait tapé 1234 au clavier.
  6. Lorsqu'on arrive en ligne 4, on demande à Python de comparer "1234" et "12345". Les deux étant différents, Python renvoie False et le stocke dans la variable autorisation.

✎ 05° Compléter maintenant ce programme qui demande à l'utilisateur son mot de passe tant que celui qu'il fournit n'est pas le bon. Il faudra vous assurer qu'on rentre bien une première fois dans le tant que, en fournissant une fausse valeur qui ne peut pas être le mot de passe réel.

1 2 3 4 5 6
mdp_reel = "12345" mdp_recu = ... while ... != ...: print("Entrez votre mot de passe :") mdp_recu = input() print("Mot de passe accepté")

✎ 06° Dans le script ci-dessous, la variable mdp_recu contiendra le mot de passe tapé par l'utilisateur et le dictionnaire les_mdp contient les bonnes associations nom - mot de passe de l'utilisateur. Lancer le programme pour voir ce qu'il fait puis répondre aux questions.

1 2 3 4 5 6 7 8 9 10 11 12
les_mdp = {"Alice": "12345", "Bob": "0000"} # Commentaire ? nom = "" # Fausse valeur initiale mdp_recu = "" # Fausse valeur initiale while nom not in les_mdp.keys(): # Commentaire ? nom = input("Nom : ") # Commentaire ? while mdp_recu != les_mdp[nom]: # Commentaire ? mdp_recu = input("Mot de passe : ") # Commentaire ? print(f"Autorisation fournie à {nom} :") # Commentaire ?

Questions :

  1. L1 : Quelle est la valeur associée à la clé "Alice" dans le dictionnaire les_mdp ?
  2. L6 : Que signifie en français l'expression nom not in les_mdp.keys() ?
  3. L9 : Que signifie en français l'expression mdp != les_mdp[nom] ?

Convertisseur Décimal vers Binaire

Regardons maintenant comment réaliser un convertisseur nombre en décimal vers binaire.

Si vous n'avez jamais vu le binaire, ce n'est pas grave. Avec ce programme, vous allez comprendre pourquoi avec 8 bits (8 cases ne pouvant contenir que 0 ou 1) on ne peut pas coder de nombres entiers supérieurs à 255.

07° Complément de connaissances avant de créer le programme de conversion. Tapez ceci dans une console Python.

>>> s = "Bonjour" >>> a = s[1:] >>> a 'onjour' >>> b = s[2:] >>> b 'njour' >>> c = s[3:] >>> c 'jour' >>> s 'bonjour'

Questions 

  1. A quoi sert visiblement de rajouter [1:], [2:], ou [3:] derrière un string ?
  2. A quoi voit-on que cela renvoie un nouveau string et non pas que cela modifie le string de base ?
  3. Les strings sont-ils muables ou immuables dans Python ?

...CORRECTION...

  1. Visiblement [1:] renvoie une copie du string mais en ne gardant que les caractères d'indice 1 et plus. On supprime donc l'ancien caractère 0.
  2. De même, [2:] renvoie une copie du string mais en ne gardant que les caractères d'indice 2 et plus. On supprime donc les caractères 0 et 1.

    De même, [3:] renvoie une copie du string mais en ne gardant que les caractères d'indice 3 et plus. On supprime donc les caractères 0, 1 et 2.

  3. On voit qu'il ne s'agit pas d'une modification du string de base puisque sur la dernière ligne, la demande de visualisation de s montre que le string n'a pas été modifié.
  4. C'est normal puisque les strings sont immuables en Python.

08° Complément de connaissances pour le programme de conversion. Tapez ceci dans une console Python : on utilise la fonction native bin() qui permet d'obtenir une conversion d'un entier en binaire (un système où les seuls chiffres disponibles sont 0 ou 1).

>>> bin(64) '0b1000000' >>> bin(65) '0b1000001' >>> bin(66) '0b1000010' >>> bin(200) '0b11001000' >>> bin(200)[2:] '11001000'

Questions 

  1. Quel est le type de la réponse de bin() ?
  2. Quelle est l'indication présente au début de la séquence permettant de savoir qu'on représente un résultat sous forme binaire ?
  3. Quelle évaluation permet d'obtenir uniquement les caractères 2 et plus de cette conversion en binaire ?

...CORRECTION...

    1. On voit que la fonction renvoie un string.
    2. On remarque qu'il y a à chaque fois '0b' en début de string.
    3. Pour supprimer ces deux caractères, il suffit donc de taper bin(200)[2:] par exemple.
    >>> bin(64) '0b1000000' >>> bin(64)[2:] '1000000' >>> bin(200) '0b11001000' >>> bin(200)[2:] '11001000'

09° Placer ce programme en mémoire. Faire quelques essais pour comprendre par exemple comment on encode 0, 1, 2, 4, 5 et 255 avec un octet (8 bits).

L'analyse du code se fait en question 10, ici on ne fait que l'utiliser.

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
# CONSTANTES NBR_BITS = 8 # Nombre de bits minimum affichés # Déclaration des fonctions def message_ouverture(): print("CONVERTISSEUR décimal en binaire") print("Entrer un nombre négatif si vous voulez sortir du convertisseur") def message_final(): print("FIN") def affichage_binaire(n): string_binaire = bin(n)[2:] # Commentaire ? if len(string_binaire) < NBR_BITS: # Commentaire ? rajout = NBR_BITS - len(string_binaire) # Commentaire ? string_binaire = "0" * rajout + string_binaire # Commentaire ? print(f"{'-' * 29} └────── {string_binaire}") # Commentaire ? def recuperer_un_entier(question): reponse = "" # "Fausse réponse" pour rentre dans le while while type(reponse) != int: # TQ reponse n'est pas un entier rep_clavier = input(question) # récupère le choix de l'utilisateur try: # Essaye de faire ceci : reponse = int(rep_clavier) # transforme rep_clavier en int except: # Si cela déclenche une Exception pass # on ne fait rien, on passe... return reponse # Programme principal nbr = 0 # Commentaire ? message_ouverture() # Commentaire ? while nbr >= 0: # Commentaire ? nbr = recuperer_un_entier("Entier à convertir en binaire : ") if nbr >= 0: # Commentaire ? affichage_binaire(nbr) # Commentaire ? message_final() # Commentaire ?

Question : Pourquoi ne peut-on pas coder plus que 255 avec un seul octet (8 bits) ? Utiliser bien entendu le programme pour parvenir à répondre.

...CORRECTION...

>>> %Run convertisseur.py CONVERTISSEUR décimal en binaire Entrer un nombre négatif si vous voulez sortir du convertisseur Entier à convertir en binaire : 0 ----------------------------- └────── 00000000 Entier à convertir en binaire : 1 ----------------------------- └────── 00000001 Entier à convertir en binaire : 2 ----------------------------- └────── 00000010 Entier à convertir en binaire : 3 ----------------------------- └────── 00000011 Entier à convertir en binaire : 254 ----------------------------- └────── 11111110 Entier à convertir en binaire : 255 ----------------------------- └────── 11111111 Entier à convertir en binaire : 256 ----------------------------- └────── 100000000 >>>

La réponse de 255 montre bien que les 8 bits sont déjà tous à 1 : si on veut rajouter un 1, il faut donc rajouter les bits d'un deuxième octet.

✎ 10° Répondre aux questions d'analyse du programme :

  1. Quelles sont les quatre fonctions déclarées dans ce programme ?
  2. Quelle est la seule variable globale de ce programme ? Est-elle lue directement par les fonctions ou est-elle transmise en tant que paramètre ? Est-il normal qu'elle n'apparaisse pas dans la partie "Constantes et variables globales" ?
  3. Que contient string_binaire (type et contenu) après exécution de la ligne 15 sur un appel comme affichage_binaire(5) ?
  4. A quoi servent les lignes 16 à 18 ? Sous quelle condition va-t-on réaliser cette action ?
  5. Commenter les lignes du programme principal et de la fonction affichage_binaire().

Jeu de calculs pour les petits

11° Notez (sans justification particulière) pour chacune des variables surlignées dans le programme ci-dessous s'il s'agit d'une variable locale ou d'une variable globale. Il ne s'agit pas d'analyser le code en détail, juste de faire attention aux déclarations.

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
import random as rd # Plus facile de taper rd que random def recuperer_un_entier(question): reponse = "" # "Fausse réponse" pour rentre dans le while while type(reponse) != int: # TQ reponse n'est pas un entier rep_clavier = input(question) # récupère le choix de l'utilisateur try: # Essaye de faire ceci : reponse = int(rep_clavier) # transforme rep_clavier en int except: # Si cela déclenche une Exception pass # on ne fait rien, on passe... return reponse def multiplication(max_a, max_b): a = rd.randint(1, max_a) b = rd.randint(1, max_b) m = 0 # Fausse valeur pour rentrer dans la boucle nbr = 0 # compteur des essais pour cette question while m != a*b: # TQ la réponse n'est pas la bonne m = recuperer_un_entier(f"Que vaut {a} x {b} = ? : ") nbr = nbr + 1 return nbr print("Donne le résultat des multiplications suivantes :") nbr_total = 0 for k in range(10): nbr_total = nbr_total + multiplication(10, 10) print(f"{nbr_total} tentatives pour trouver 10 multiplications !")

...CORRECTION...

1 2 3 Locale 4 Locale 5 6 Locale 7 8 9 10 11 12 13 Locales 14 Locale 15 Locale 16 Locale 17 Locale 18 19 20 21 22 23 24 Globale 25 26 27
import random as rd # Plus facile de taper rd que random def recuperer_un_entier(question): reponse = "" # "Fausse réponse" pour rentre dans le while while type(reponse) != int: # TQ reponse n'est pas un entier rep_clavier = input(question) # récupère le choix de l'utilisateur try: # Essaye de faire ceci : reponse = int(rep_clavier) # transforme rep_clavier en int except: # Si cela déclenche une Exception pass # on ne fait rien, on passe... return reponse def multiplication(max_a, max_b): a = rd.randint(1, max_a) b = rd.randint(1, max_b) m = 0 # Fausse valeur pour rentrer dans la boucle nbr = 0 # compteur des essais pour cette question while m != a*b: # TQ la réponse n'est pas la bonne m = recuperer_un_entier(f"Que vaut {a} x {b} = ? : ") nbr = nbr + 1 return nbr print("Donne le résultat des multiplications suivantes :") nbr_total = 0 for k in range(10): nbr_total = multiplication(10, 10) + nbr_total print(f"{nbr_total} tentatives pour trouver 10 multiplications !")

12° Expliquez pourquoi renommer la variable nbr_total en nbr ne poserait aucun problème alors qu'il existe déjà une variable nommée nbr dans l'une des fonctions.

...CORRECTION...

Trois cas se présentent :

  1. Soit l'interpréteur Python lit nbr dans le programme principal. Il va alors chercher dans l'espace des noms global du programme principal.
  2. Soit l'interpréteur Python lit nbr dans une fonction où aucun paramètre d'entrée ne s'appelle nbr et où il n'y a eu aucune affectation nbr = .... Il va alors chercher dans l'espace des noms global du programme principal.
  3. Soit l'interpréteur Python lit nbr dans une fonction où un paramètre porte ce nom ou où on a réalisé une affectation nbr = .... Il va alors chercher dans l'espace des noms local de la fonction.
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
import random as rd # Plus facile de taper rd que random def recuperer_un_entier(question): reponse = "" # "Fausse réponse" pour rentre dans le while while type(reponse) != int: # TQ reponse n'est pas un entier rep_clavier = input(question) # récupère le choix de l'utilisateur try: # Essaye de faire ceci : reponse = int(rep_clavier) # transforme rep_clavier en int except: # Si cela déclenche une Exception pass # on ne fait rien, on passe... return reponse def multiplication(max_a, max_b): a = rd.randint(1, max_a) b = rd.randint(1, max_b) m = 0 # Fausse valeur pour rentrer dans la boucle nbr_fct = 0 # compteur des essais pour cette question while m != a*b: # TQ la réponse n'est pas la bonne m = recuperer_un_entier(f"Que vaut {a} x {b} = ? : ") nbr_fct = nbr_fct + 1 return nbr_fct print("Donne le résultat des multiplications suivantes :") nbr_pp = 0 for k in range(10): nbr_pp = multiplication(10, 10) + nbr_pp print(f"{nbr_pp} tentatives pour trouver 10 multiplications !")

✎ 13° On considère qu'on vient d'appeler la fonction recuperer_un_entier(). L'interpréteur est donc en ligne 3.

  1. Fournir les lignes suivies par l'interpréteur (jusqu'à sortir de la fonction) si l'utilisateur tape d'abord 'B' puis '12'.
  2. Quelle est le type et la valeur de la réponse que va faire la fonction sur cet exemple ?
  3. 1 2 3 4 5 6 7 8 9 10 11
    import random as rd # Plus facile de taper rd que random def recuperer_un_entier(question): reponse = "" # "Fausse réponse" pour rentre dans le while while type(reponse) != int: # TQ reponse n'est pas un entier rep_clavier = input(question) # récupère le choix de l'utilisateur try: # Essaye de faire ceci : reponse = int(rep_clavier) # transforme rep_clavier en int except: # Si cela déclenche une Exception pass # on ne fait rien, on passe... return reponse

✌ 14° On considère maintenant que le nom de recuperer_un_entier() est suffisamment clair pour se passer d'explications supplémentaires. Fournir une explication globale du fonctionnement du programme pour quelqu'un de la classe qui n'aurait pas compris. Le but est de suivre le déroulé du programme pour en résumer les points importants. Une fois que vous pensez pouvoir l'expliquer clairement, appeler l'enseignant.

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
import random as rd # Plus facile de taper rd que random def recuperer_un_entier(question): reponse = "" # "Fausse réponse" pour rentre dans le while while type(reponse) != int: # TQ reponse n'est pas un entier rep_clavier = input(question) # récupère le choix de l'utilisateur try: # Essaye de faire ceci : reponse = int(rep_clavier) # transforme rep_clavier en int except: # Si cela déclenche une Exception pass # on ne fait rien, on passe... return reponse def multiplication(max_a, max_b): a = rd.randint(1, max_a) b = rd.randint(1, max_b) m = 0 # Fausse valeur pour rentrer dans la boucle nbr = 0 # compteur des essais pour cette question while m != a*b: # TQ la réponse n'est pas la bonne m = recuperer_un_entier(f"Que vaut {a} x {b} = ? : ") nbr = nbr + 1 return nbr print("Donne le résultat des multiplications suivantes :") nbr_total = 0 for _ in range(10): nbr_total = nbr_total + multiplication(10, 10) print(f"{nbr_total} tentatives pour trouver 10 multiplications !")

Vous avez vu comment réaliser des interfaces textuelles avec les deux fonctions print() input(). Dans l'activité suivante, vous allez voir quelques interfaces graphiques.

3 - FAQ

Rien pour le moment

Maintenant que nous avons vu comment créer un programme, nous allons compléter les notions de fonctions, de boucles et d'instructions conditionnelles dans le but de réaliser des programmes de plus en plus complexes.

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