11 - Boucles non bornées
Nous avons vu les boucles bornées : les boucles qui travaillent en boucle un nombre de fois défini à l'avance.
Nous avons vu les instructions conditionnelles : comment agir en fonction des besoins.
Voyons aujourd'hui les boucles non bornées : on agit en boucle tant qu'une condition est évaluée à True.
Documents de cours : open document ou pdf
Evaluation ✎ : questions 19-21-22-23-24
Evaluation ✌ : question 20
1 - Rappel préalable : le module random
Rappel sur le hasard dans Python
La fonction randint() du module random permet d'obtenir un entier au hasard compris entre le nombre de départ d fourni (inclus) et le nombre de fin f fourni (inclus) : [d, f].
Exemple : random.randint(0, 5) va renvoyer un nombre pouvant être 0, 1, 2, 3, 4 ou 5.
Pour obtenir un nombre aléatoire compris entre -50 et +200, il suffit de faire ceci :
1
2 |
|
Différence énorme avec range pour lequel on transmet une valeur de fin non incluse dans l'intervalle des valeurs possibles : [d, f[.
Exemple : range(0, 5) va permettre de récupérer une à une les valeurs 0, 1, 2, 3, et 4. Pas 5.
01° Taper ceci dans la console pour comprendre comment réaliser un tirage aléatoire entre 5 et 10 : le résultat sera toujours soit 5, soit 6, soit 7, soit 8, soit 9, soit 10.
>>> import random
>>> random.randint(5, 10)
?
>>> random.randint(5, 10)
?
>>> random.randint(5, 10)
?
02° Que doit-on taper dans la console pour obtenir un résultat simulant un dé à 6 faces ?
...CORRECTION...
>>> random.randint(1, 6)
03° Réaliser une fonction de() recevant un paramètre nb qui est le nombre de faces d'un dé et qui renvoie un nombre entier aléatoire entre 1 et nb.
1
2
3
4
5
6
7
8
9
10 |
|
PRECONDITION : lors de l'appel de la fonction, il faudra envoyer un nombre nb qui soit un entier positif strictement supérieur à 1.
...CORRECTION...
1
2
3
4
5
6
7
8
9
10 |
|
2 - Boucle non bornée tant que / while
Nous allons donc parler de la boucle TANT QUE ou WHILE en anglais.
1 - Définition Boucle non bornée : la boucle TANT QUE / WHILE
Définition d'une boucle : Une boucle est un bloc d’instructions qui va être réalisé zéro, une ou plusieurs fois d’affilé.
Définition d'une boucle non bornée : Une boucle non bornée est une boucle dont l’exécution dépend de l’évaluation d’une expression qu'on nommera condition de poursuite.
Le principe est simple :
- On évalue la condition de poursuite à VRAI ou FAUX
- SI la condition de poursuite est évaluée à VRAI, on réalise le bloc, et on revient à l'étape 1.
- SINON, on quitte définitivment la boucle.
On parle de boucle non bornée puisqu'on ne connait pas à l'avance le nombre de fois où la boucle va être réalisée : on réalise la boucle TANT QUE la condition de poursuite sera évaluée à VRAI. WHILE en anglais. Il n'y a pas de nombre limite au bout duquel on quitte la boucle. Ca peut tourner à l'infini.
2 - Déclaration en Python
En Python, c'est l'indentation qui renseigne sur l'appartenance des instructions à la boucle. Le mot-clé pour déclarer une boucle TANT QUE est while :
L1 while condition de poursuite:
L2 instruction A
L3 instruction B
L4 instruction C
L5
L6 suite du programme
Le principe est donc :
- D'évaluer la condition de poursuite.
- SI elle est évaluée à True, on réalise les lignes 2-3-4 puis on revient à la ligne 1 et on évalue à nouveau la condition de poursuite en ligne 1.
- SINON, c'est qu'elle est évaluée à False, on quitte la boucle et on part directement en ligne 6.
Commençons par un exemple simple : réaliser l'équivalent d'une boucle FOR partant de 0 jusqu'à atteindre 40, de 10 en 10 : 0 puis 10 puis 20 puis 30 puis 40.
04° Placer le programme sur Python Tutor. Observer son fonctionnement. Pourquoi peut-on dire qu'une boucle TANT QUE est un mélange de boucle POUR et d'instruction conditionnelle ?
1
2
3
4
5
6
7 |
|
CLIQUEZ ICI POUR VOIR LE DEROULEMENT SEQUENTIEL
x :
x < 40 ? :
...CORRECTION...
Avant chaque nouveau tour de boucle, on évalue la condition, un peu comme avec un IF.
Si la condition renvoie VRAI, on réalise l'action puis on renvoie au début de la boucle où on va évaluer une nouvelle fois la condition pour voir si on recommence, ou pas.
Il s'agit donc d'une sorte de "boucle conditionnelle".
Comme pour if for def, c'est l'indentation de 4 espaces qui permet d'indiquer quelles sont les instructions du bloc à exécuter en boucle.
05° Réaliser un programme utiliser un while pour afficher les nombres 15, 35, 55, 75, 95... jusqu'à atteindre 20015 pour le dernier. De 20 en 20 donc.
...CORRECTION...
1
2
3
4
5
6
7 |
|
06° Quelle est l'erreur présente ici et qui provoque une boucle infinie ?
1
2
3
4
5
6
7 |
|
...CORRECTION...
Il y a une mauvaise indentation de la ligne 5 : l'incrémentation de la variable x n'est plus à l'intérieur de la boucle.
On ne va exécuter cette ligne qu'après être sorti de la boucle.
Le problème ? La condition pour continuer dépend de x, or on ne change jamais sa valeur lors de l'exécution de la boucle.
x vaut 0 au début et garde cette valeur... à l'infini.
Comme vous pouvez le voir, cette structure est plus complexe à utiliser qu'une boucle FOR :
- Ligne 1 : il faut d'abord initialiser la variable de boucle x.
- Ligne 3 : il faut préciser fournir la condition de poursuite.
Question : pourquoi vouloir utiliser un while alors qu'on peut utiliser un for qui a l'air plus simple à utiliser ?
1
2
3
4
5 |
|
1
2
|
|
Réponse : Un TANT QUE permet de faire plus de choses qu'une boucle POUR.
3 - POUR ou TANT QUE ? Bornée ou non bornée
- Si on connait à l'avance le nombre de fois où on va devoir agir, on utilise une boucle POUR.
- Si on ne peut pas savoir à l'avance le nombre de fois où on va devoir agir, on utilise une boucle TANT QUE.
C'est la condition de poursuite fournie qui va permettre de faire le choix de continuer ou pas.
La boucle POUR est une boucle bornée.
La boucle TANT est une boucle non bornée.
Exemple 1
Un exemple concret avec le remplissage de votre sac pour aller au lycée :
1
2
3
4
5 | while vous_avez_encore_des_choses_a_prendre:
prendre_objet_suivant()
mettre_cet_objet_dans_votre_sac()
partir_au_lycée()
|
Vous allez donc faire les lignes 1-2-3 en boucle tant que vos affaires ne sont pas totalement faites.
Exemple 2
Un autre exemple, en passant un peu plus en gestion informatique : le passage en cuisine pour se nourrir avec l'utilisation du prédicat j_ai_faim() qui renvoie True si vous avez encore faim.
1
2
3
4
5
6
7
8 | rentrer_en_cuisine()
while j_ai_faim():
manger_un_truc()
boire__un_verre()
attendre_un_peu()
quitter_la_cuisine()
|
Vous allez donc faire les lignes 3-4-5-6 en boucle à chaque fois que la fonction prédicat j_ai_faim() renvoie encore et encore True.
07-A° Mettre l'exemple ci-dessous en mémoire. Lancer le programme.
Quelques explications : à chaque tour de boucle
- On tire 3 fois un dé à 6 faces et on calcule le total obtenu.
- On affiche ce total (entre 3 (on tire 3 "1" sur les dés par malchance) et 18 (on tire 3 "6" sur les dés par chance).
La condition de poursuite de la boucle est d'avoir obtenu un total inférieur à 16 sur les dés.
1
2
3
4
5
6
7
8
9
10
11
12
13 |
|
Questions
- Aurait-on pu faire pareil avec une boucle bornée ?
- Pourquoi avoir placé 0 initialement dans la variable total sur la ligne 7 ?
- Donner une autre valeur d'initialisation qu'on aurait utiliser en ligne 7 sans que cela change quoi que ce soit au déroulé du programme ?
...CORRECTION...
- La boucle bornée n'est pas possible ici à cause du côté aléatoire : on ne sait absolument pas combien de lancer de dés il va falloir faire pour obtenir 16, 17 ou 18 et ainsi sortir de la boucle.
- On place 0 car on est ainsi certain de pouvoir réaliser au moins une fois la boucle.
- On aurait pu placer n'importe quel entier strictement inférieur à 16.
07-B° Quelqu'un a mal copié le programme précédent et a oublié de mettre la ligne 7.
1
2
3
4
5
6
7
8
9
10
11
12
13 |
|
Question : Expliquer l'erreur d'exécution qui apparaît alors.
while total < 16:
NameError: name 'total' is not defined
...CORRECTION...
Lorsqu'on arrive en ligne 9, on demande à l'interpréteur d'évaluer l'expression total < 16. Or, la variable total n'existe pas en mémoire puisqu'on ne l'a pas initialisée sur la ligne 7 manquante.
L'erreur typique vient du fait qu'en lisant vite, on voit qu'il y a une affectation de total en ligne 10. Oui, mais cela veut bien dire qu'on ne peut pas l'évaluer en ligne 9.
07-C° Quelqu'un a encore mal copié le programme précédent.
1
2
3
4
5
6
7
8
9
10
11
12
13 |
|
Question : Expliquer l'erreur d'exécution qui apparaît alors.
while total < 16:
NameError: name 'total' is not defined
...CORRECTION...
Même principe : total n'existe pas car ligne 7 on crée la variable totol... Pour un humain, cela pourrait passer. Pas pour l'ordinateur qui n'a aucune compréhension de ce que vous voulez faire.
4 - Choix attentif de la valeur initiale
Les variables nécessaires à l'évaluation du TANT QUE doivent toutes être définies avant la ligne du TANT QUE.
Si la condition est basée sur une variable qui est calculée dans le bloc de la boucle elle-même, comment faire ? Facile : on initialise cette variable avec une "fausse valeur" initiale de façon à pouvoir rentrer dans la boucle au départ.
Exemple : en ligne 7, on place 0 dans total, une "fausse valeur" pour la somme des dés. Mais puisque ce 0 est plus petit que 16, c'est un bon choix car on pourra bien rentrer une première fois dans la boucle et calculer une première valeur de jet de dés.
1
2
3
4
5
6
7
8
9
10
11
12
13 |
|
Un exemple sur le thème économique :
08-A° Imaginons que vous ayez une somme d'argent à investir. Tous les mois, votre placement vous rapporte 2% d'intérêt par mois (cela veut dire que la somme d'argent est multipliée par 1,02 tous les mois).
Nous voudrions savoir au bout de combien de mois vous allez avoir 2000 euros sur ce compte.
Question : comment écrire la condition_de_poursuite de l'action laisser_l_argent_sur_le_compte_un_mois_de_plus() ?
- while argent > 2000:
laisser_l_argent_sur_le_compte_un_mois_de_plus() - while argent >= 2000:
laisser_l_argent_sur_le_compte_un_mois_de_plus() - while argent < 2000:
laisser_l_argent_sur_le_compte_un_mois_de_plus() - while argent <= 2000:
laisser_l_argent_sur_le_compte_un_mois_de_plus()
...CORRECTION...
Il faut continuer à laisser l'argenet tant que nous ne disposons pas de 2000 euros sur le compte. Il faut donc choisir la proposition C :
while argent < 2000:
laisser_l_argent_sur_le_compte_un_mois_de_plus()
08-B° Voici un algorithme de calcul de la somme d'argent au fil des mois :
- On crée un compteur de mois valant 0 initialement
- On définit la somme initiale d'argent sur le compte (1200 euros).
- TANT QUE l'argent sur le compte est inférieur à 2000 euros :
- On multiplie par 1.02 l'argent sur le compte (l'intérêt est de 2 % sur l'exemple)
- On incrémente de 1 le compteur de mois
- Une fois sorti de la boucle, on affiche la valeur du compteur qui correspond au nombre de mois nécessaires pour atteindre au moins 2000 euros sur le compte.
Questions :
- Comprendre le principe de l'algorithme
- Calculer (sans faire de programme) la somme sur le compte après 3 mois (3 tours de boucle donc) en plaçant 1200 euros initialement. On prendra un taux d'intérêt de 2 % par mois. Réalisez les calculs en utilisant la console de Python comme une simple calculatrice.
...CORRECTION...
On commence avec un compteur nb_mois faisant référence à 0 et une variable argent faisant référence à 1200 euros.
On fait un premier tour de boucle puisque argent vaut moins que 2000 euros.
- On incrémente nb_mois qui passe à 1
- La nouvelle somme d'argent vaut 1200*1.02, soit 1224.0 euros.
- On affiche la somme sur le compte, 1224.0 euros.
- Le programme attend que l'utilisateur valide en appuyant sur ENTREE
On fait un deuxième tour de boucle puisque argent vaut moins que 2000 euros.
- On incrémente nb_mois qui passe à 2
- La nouvelle somme d'argent vaut 1224.0*1.02, soit 1248.48 euros.
- On affiche la somme sur le compte, 1248.48 euros.
- Le programme attend que l'utilisateur valide en appuyant sur ENTREE
On fait un troisième tour de boucle puisque argent vaut moins que 2000 euros.
- On incrémente nb_mois qui passe à 2
- La nouvelle somme d'argent vaut 1248.48.0*1.02, soit 1273.4496000000001 euros.
- On affiche la somme sur le compte, 1273.4496000000001 euros.
- Le programme attend que l'utilisateur valide en appuyant sur ENTREE
08-C° Lancer le programme ci-dessous pour voir comment il fonctionne. Il faut taper sur ENTREE pour confirmer la poursuite du déroulement.
1
2
3
4
5
6
7
8
9
10 |
|
Explication de la ligne 8 : la fonction native input() permet simplement ici d'attendre l'appui sur la touche ENTREE pour permettre la suite de l'exécution. Le programme ne repartira donc en ligne 4 qu'après votre appui sur ENTREE.
Question finale
Trouver les lignes du programme qui correspondent aux actions suivantes :
- Ligne ? : On crée un compteur de mois valant 0 initialement
- Ligne ? : On définit la somme initiale sur le compte.
- Ligne ? : Tant que l'argent sur le compte est inférieur à 2000 euros :
- Ligne ? : On calcule la nouvelle somme d'argent sur le compte à la fin du mois
- Ligne ? : On affiche la somme d'argent sur le compte
- Ligne ? : On incrémente le compteur de mois de 1
- Ligne ? : On crée une pause en demandant à l'utilisateur d'appuyer sur ENTREE
- Ligne ? : Une fois sorti de la boucle, on affiche la valeur du compteur qui correspond au nombre de mois nécessaire pour avoir 2000 euros sur le compte.
...CORRECTION...
- Ligne 1 : On crée un compteur de mois valant 0 initialement
- Ligne 2 : On définit la somme d'argent initialement sur le compte.
- Ligne 4 : Tant que l'argent sur le compte est inférieur à 2000 euros :
- Ligne 6 : On calcule la nouvelle somme d'argent sur le compte à la fin du mois
- Ligne 7 : On affiche la somme d'argent sur le compte
- Ligne 5 : On incrémente le compteur de mois de 1
- Ligne 8 : On crée une pause en demandant à l'utilisateur d'appuyer sur ENTREE
- Ligne 10 : Une fois sorti de la boucle, on affiche la valeur du compteur qui correspond au nombre de mois nécessaire pour avoir 2000 euros sur le compte.
2 % par mois c'est beaucoup ou pas ?
Pour répondre à la question, vous devriez vous rendre compte maintenant, qu'il suffit de multiplier la somme initiale par 1.02 pendant 12 mois :
>>> 1.02 * 1.02 * 1.02 * 1.02 * 1.02 * 1.02 * 1.02 * 1.02 * 1.02 * 1.02 * 1.02 * 1.02
1.2682417945625455
Et cela donne presque 1.27, soit un taux d'intérêt de 27 % par an !
Note : plutôt que de taper les multiplications, vous pouvez également juste demander à Python de calculer 1.02 puissance 12.
>>> 1.02 ** 12
1.2682417945625455
5 - Un peu de logique : TANT QUE, poursuite et arrêt
Lien entre poursuite et arrêt
Pour résoudre un problème avec un TANT QUE, on utilise une condition de poursuite.
1
2 |
|
Or, parfois, lorsqu'on réfléchit, on tombe plutôt sur une condition d'arrêt de la boucle...
Comment faire alors ?
C'est facile :
- Si la condition d'arrêt donne True, c'est que la condition de poursuite vaut False.
- Si la condition d'arrêt donne False, c'est que la condition de poursuite vaut True.
On peut donc trouver la condition de poursuite en inversant la condition d'arrêt avec un NON logique (not en Python).
poursuite = not arrêt
Il suffit alors d'écrire ceci :
1
2 |
|
Conclusion
En conclusion, on peut programmer une boucle TANT QUE en utilisant les deux conditions :
- si on connaît la condition de poursuite de l'action à faire, on l'utilise directement dans le TANT QUE.
- soit on connaît la condition d'arrêt de l'action, on l'utilise en l'inversant avec un NON dans le TANT QUE.
Exemple : on laisse l'argent en banque tant qu'on ne dispose pas de 2000 euros.
Ici, la condition de poursuite est donc argent < 2000
1 |
|
Exemple : on arrête de laisser l'argent en banque dès qu'on a 2000 euros ou plus sur le compte.
La condition d'arrêt est donc argent >= 2000
1 |
|
Parfois on trouve facilement les deux conditions (arrêter ou continuer). Parfois, seule l'une des deux conditions est facile à trouver.
C'est pour cela que connaitre la technique du not est important.
09° La condition de poursuite de la boucle était d'avoir obtenu un résultat r strictement inférieur à 16 sur les dés.
La condition d'arrêt est donc d'avoir un résultat de 16 ou plus avec nos dés.
Action : reécrire le TANT QUE en utilisant plutôt la condition d'arrêt. Tester pour vérifier que le programme a exactement le même fonctionnement.
1
2
3
4
5
6
7
8
9
10
11
12
13 |
|
...CORRECTION...
1
2
3
4
5
6
7
8
9
10
11
12
13 |
|
10° On veut créer un jeu vidéo.
- Le joueur commence sur un premier niveau de jeu relativement facile pour se faire la main.
- Lorsqu'il a acquis 500 points, il passera au niveau 2.
- Lorsqu'il aura acquis 1000 points, il passera au niveau 3.
Question : Quel est le programme imaginaire (A ou B) adapté à la situation décrite ?
Programme A :
1
2
3
4
5
6
7
8
9 |
|
Programme B :
1
2
3
4
5
6
7
8
9 |
|
On imagine bien entendu que les fonctions jouer_niveau_X() parviennent à modifier la valeur de la variable xp.
...CORRECTION...
Il s'agit de la solution B : on doit changer sur le niveau 1 TANT QUE les xp sont inférieurs à 500.
Voyons maintenant un exemple plus graphique :
- On place une tortue avec un angle d'orientation et des coordonnées (x, y) aléaotoires.
- On lui demande d'avancer TANT QUE sa coordonnée x est inférieure à 300.
11° Placer ce code en mémoire. Lancer pour visualiser le déplacement de la tortue. Aucune question pour l'instant, juste de la visualisation.
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 |
|
12° Analyser le code puis répondre à ces questions :
Remarque ligne 24 : xcor() est une méthode des objets Turtle permettant de récupérer la coordonnée x de l'objet.
- Quelles sont les valeurs initiales possibles des valeurs initiales en x et de l'angle de base du "stylo" stocké dans la variable s ?
- Avec la valeur initiale de x imposée en ligne 7, pourquoi est-on certain de parvenir à rentrer au moins une fois dans la boucle TANT QUE ?
- Avec l'angle créé en ligne 9 (entre -45° et +45° donc), est-on certain de percuter le "mur" de droite ?
...CORRECTION...
Ligne 7 : x = rd.randint(-200, 200)
: on voit que x va avoir aléatoirement une valeur entre -200 et +200, donc nécessairement inférieure à 300. Comme la condition pour rentrer dans la boucle est (ligne 23) d'être inférieure à 300, nous sommes certain de rentrer au moins une fois.
Pour l'angle, on a (ligne 9) un angle entre -45° et +45° : on va donc percuter le mur (on ne risque pas d'avoir un stylo qui remonte avec un angle de +90° ou qui redescend avec un angle de -90°).
13° Remplacer la ligne 9 par ceci : l'angle est maintenant aléatoire entre 90° et 180°. La tortue va donc se diriger quelque part à gauche, mais jamais vers la droite.
9 |
|
Question
- Pourquoi obtient-on une boucle TANT QUE infinie ?
...CORRECTION...
On ne pourra jamais percuter le mur de droite car la tortue part à gauche...
Nous ne sortirons donc jamais de la boucle car la condition restera VRAI à jamais.
D'où le terme "BOUCLE INFINIE" : le programme va faire la séquence L23-L24-L23-L24-L23... sans jamais pouvoir s'interrompre.
Voyons maintenant le principe de la boucle infinie.
6 - Boucle infinie
Pour créer une boucle qui ne s'arrête jamais, on choisit une condition de poursuite qui ne pourra jamais être évaluée à False. Commme quoi ? C'est simple : True !
1
2
3 |
|
La condition de poursuite étant juste True, on va donc effectuer L2-L3 à l'infini.
Ce bouclage peut être voulu (comme sur un système embarqué qui ne doit jamais arrêter son programme) ou involontaire. Si c'est involontaire, c'est le drame car on ne pourra pas prendre la main à moins de stopper le programme.
14° Mettre le programme en mémoire.
Lancer la fonction lancer_animation() depuis la console.
Question 1 : Localiser la boucle et vérifier que l'animation ne s'arrête jamais. Ca peut être long :o)
Question 2 : Quelles sont les fonctions qui sont chargées de gérer ces tâches ?
- effacer le dessin de cercle réalisé par l'un des crayons
- déplacer le crayon de la balle
- redessiner la balle à cet endroit
Question 3 (optionnelle) : Si vous vous sentez assez à l'aise, prenez le temps de comprendre vraiment comment le programme fonctionne.
>>> lancer_animation()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123 |
|
3 - Jeu interactif console
Nous allons réaliser un jeu demandant en boucle à l'utilisateur de trouver un nombre compris entre 0 et 100, tant qu'il ne trouve pas la bonne réponse.
Nous allons donc réaliser une interface entre notre programme et l'utilisateur humain et nous utiliserons la console, c'est plus facile que de construire une interface graphique.
- ORDINATEUR vers UTILISATEUR en utilisant la console :
- la fonction native print() affiche des choses dans la console.
- UTILISATEUR vers ORDINATEUR en utilisant la console :
- la fonction native input() renvoie ce que l'utilisateur tape sur le clavier. L'utilisateur valide sa réponse en appuyant sur ENTREE.
Bref, petit complément.
7 - Fonction native input()
Cette fonction renvoie la saisie clavier de l'utlisateur.
Prototype : input(prompt:str) -> str:
Cette fonction fait trois choses :
- La fonction affiche le string prompt qu'elle a reçu (c'est la question qu'on veut poser).
- La fonction attend que l'utilisateur tape quelque chose sur le clavier et finalise par l'appui sur ENTREE.
- La fonction renvoie le texte tapé par l'utilisateur, sous forme d'un string.
C'est pour cela qu'un programme n'avance plus tant que l'utilisateur n'a pas validé sa réponse. On peut donc l'utiliser comme une sorte de PAUSE lorsqu'on utilise l'interface CONSOLE.
Voici l'exemple typique :
1
2
3
4 |
|
Sur la ligne 2, on voit que la variable nom va faire référence à ce que l'utilisateur va répondre lorsqu'on lui posera la question "Quel est votre nom ? ".
Un exemple d'utlisation
Début du programme
Quel est votre nom ? Toto l'asticotENTREE
Bonjour Toto l'asticot
15° Utiliser le programme pour être certain de comprendre comment fonctionne cette nouvelle fonction native input().
1
2
3
4 |
|
16° Réaliser un programme qui demande votre nom et votre age et qui affiche ENSUITE le nom qu'on a enregistré et le double de l'age enregistré.
Avez-vous une idée de la raison du comportement "étrange" de votre programme ?
...CORRECTION...
Vous avez certainement réalisé quelque chose qui ressemble à ceci :
1
2
3
4
5 |
|
Et un exemple d'utilisation :
Quel est votre nom ? BobENTREE
Quel est votre age ? 17ENTREE
Bonjour Bob
Vous avez 1717 ans !
On retrouve donc le fait qu'on travaille visiblement sur une variable age qui contient un string.
17° Tester ce programme qui parvient à transformer la donnée fournie par l'utilisateur en integer en utilisant la fonction native int().
1
2
3
4
5
6
7 |
|
Et un exemple d'utilisation :
Quel est votre nom ? BobENTREE
Quel est votre age ? 17ENTREE
Bonjour Bob
Vous avez 34 ans !
Reprenons notre jeu de recherche d'un nombre aléatoire compris entre 0 et 100.
18° Regarder le programme fourni qui permet de jouer et dans lequel il faut trouver un nombre POSITIF. Il manque uniquement la "fausse" valeur initiale à placer dans la variable proposition en ligne 17.
Question : Expliquer pourquoi il n'est pas malin de mettre 0 sur cette ligne 17 cette fois.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 |
|
...CORRECTION...
Mettre 0 n'est pas malin car il est possible que la bonne réponse soit 0 : ce nombre est aléatoirement possible.
Il faudrait placer un nombre impossible à obtenir, comme -1 par exemple : on précise que le nombre à trouver doit être positif.
✎ 19° Expliquer comment fonctionne la boucle proposée en ligne 19 : dans quel cas va-t-on faire ou refaire un tour de boucle ? dans quel cas va-t-on sortir de la boucle ?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 |
|
✌ 20° Modifier la fonction affichage() pour obtenir un jeu plus facile : on donne des indices sur la valeur du nombre si la valeur n'est pas bonne. Exemple :
Quel est le nombre mystère à votre avis ? 50
Le nombre mystère est plus petit
Quel est le nombre mystère à votre avis ? 25
Le nombre mystère est plus grand
Quel est le nombre mystère à votre avis ? 37
Le nombre mystère est plus petit
Quel est le nombre mystère à votre avis ? 31
Le nombre mystère est plus petit
Quel est le nombre mystère à votre avis ? 28
Le nombre mystère est plus grand
Quel est le nombre mystère à votre avis ? 29
Le nombre mystère est plus grand
Quel est le nombre mystère à votre avis ? 30
Bien vu !
FIN
4 - Equivalence
8 - Remplacer un POUR par un TANT QUE
Nous avons vu que :
- La boucle bornée POUR / FOR est programmable naturellement en Python avec un for.
- La boucle non bornée TANT QUE / WHILE est programmable naturellement avec un while.
Néanmoins, on peut remplacer les for par des while.
Ce n'est pas "naturel" mais on peut.
Deux fonctions qui de l'extérieur donneront la même chose :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 |
|
Il est clair qu'on a recrée la variable de boucle x à l'aide d'un while et que la fonction somme_v2() est donc plus longue et plus complexe à comprendre.
21° Tester les deux versions pour vérifier qu'elles font bien la même chose.
On devrait bien calculer ici 1 + 2 + 3 + 4 + 5 = 15.
>>> somme_v1(5)
15
>>> somme_v2(5)
15
On remarquera néanmoins qu'utiliser un while, alors qu'on a clairement plutôt une boucle bornée, crée au final un code plus compliqué.
- Il faut initialiser la variable de boucle x
- Il ne faut pas oublier de l'incrémenter de 1 à chaque tour de boucle, sinon on crée une boucle infinie !
9 - Remplacer un TANT QUE par un POUR
Voyons maintenant l'inverse : on peut stopper un POUR avant sa fin réelle à l'intérieur d'une fonction, puisqu'on sort définitivement de la fonction une fois qu'on rencontre un return.
On peut donc parfois programmer une boucle non bornée en utilisant un for associé à return plutôt que d'utiliser directement un while. J'ai noté parfois car cela est possible si il n'est pas possible de connaître la valeur maximale du nombre de tours de boucle.
Exemple : deux versions d'une fonction qui renvoie le premier mot de plus de 5 lettres trouvés dans une phrase.
On notera qu'on utilise l'espace comme caractère de séparation dans la phrase pour créer le tableau des mots.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 |
|
✎ 21° Tester les deux versions du programme en faisant les appels pour une même phrase.
>>> premier_mot_v1("Bon, alors ça marche ou pas ce truc ?")
'alors'
>>> premier_mot_v2("Bon, alors ça marche ou pas ce truc ?")
'alors'
Question
Noter un commentaire pour chaque ligne de ces fonctions : les commentaires devront expliquer en français ce que vont chaque ligne de la fonction.
Si vous bloquez, pensez à me contacter.
10 - Conclusion : BORNEE ou NON BORNEE
Avant de programmer, il convient de se demander si on a affaire à une boucle bornée ou une boucle non bornée car cela évitera que partir dans la mauvaise direction.
- Boucle bornée : for
- Boucle non bornée sans nombre maximum de tours: while
- Boucle non bornée avec un nombre maximim de tours: while ou for+return
5 - Exos
✎ 22° Compléter la condition du programme ci-dessous : il génére en boucle le lancer de 3 dés à 6 faces. Vous devez faire relancer tant que la somme des trois dés n'est pas supérieure ou égale à 13.
1
2
3
4
5
6
7
8
9
10
11 | import random
somme = 0
while CONDITION :
de1 = random.randint(1,6)
de2 = random.randint(1,6)
de3 = random.randint(1,6)
somme = de1 + de2 + de3
print(f"Les dés donnent {de1} - {de2} - {de3} pour un total de {somme}")
|
Votre petite soeur ou votre petit frère, ou un cousin ou une cousine, apprend que vous êtes en informatique au lycée. Malheur ! Il n'arrête pas de vous demander de lui fabriquer un jeu. Pour calmer ses ardeurs, vous décidez de lui concevoir un jeu de multiplication : la fonction tire deux nombres au hasard et demande le résultat de la multiplication tant que le résultat n'est pas bon. La fonction renvoie le nombre de tentatives, un au minimum donc.
✎ 23° Compléter la fonction multiplication pour qu'elle fonctionne correctement.
Il faudra juste trouver la bonne condition à mettre sur le while à la place de True.
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 | import random as rd
def multiplication(max_a, max_b):
'''Fonction qui tire au hasard deux nombres et demande à l'utilisateur le résultat de leur multiplication, tant que le résultat n'est pas bon !
::param max_a(int) :: la valeur maximale du premier tirage
::param max_b(int) :: la valeur maximale du deuxième tirage
::return (int) : renvoie le nombre essai de tentatives
'''
a = rd.randint(1, max_a)
b = rd.randint(1, max_b)
m = 0 # m contiendra la valeur que l'utilisateur pense être a*b
essai = 0
while True :
m = input(f"Que vaut {a} x {b} = ? : ")
m = int(m)
essai = essai + 1
return essai
print("Donne le résultat des multiplications suivantes.")
nbr = 0
for x in range(10):
nbr = multiplication(10,10) + nbr
print(f"{nbr} tentatives pour trouver 10 multiplications !")
|
✎ 24° Créer un programme qui demande "Voulez-vous continuer ?". Tant qu'on ne tape pas "N", le programme doit afficher un message puis reposer la question.
6 - FAQ
Rien pour l'instant
Activité publiée le 01 11 2020
Dernière modification : 04 10 2022
Auteur : ows. h.