Outils Pour

Identification

Infoforall

10 - Boucles Bornées


Vous auriez vraiment envie de faire cela sans boucle ?
1 2 3 4 5 6 7 8 9 10
import turtle as trt couleurs = ["gold", "white", "blue" ] crayon = trt.Turtle() crayon.speed(0) trt.bgcolor('black') for x in range(800): crayon.pencolor(couleurs[x % 3]) crayon.width(x//100 + 1) crayon.forward(x) crayon.left(59)

Evaluation : 5 questions

  questions 05-12-13A-13B

  question 09C

DM 🏠 : Non

Documents de cours : open document ou pdf

1 - Précisions sur la boucle POUR

Pour faire s'afficher fois la même chose plusieurs fois, on peut écrire ce programme :

1 2 3 4 5 6 7 8 9 10 11 12 13 14
# Déclaration des CONSTANTES TEXTE = "J'aime bien les copier coller !" # Programme principal print(TEXTE) print(TEXTE) print(TEXTE) print(TEXTE) print(TEXTE) print(TEXTE) print(TEXTE) print(TEXTE) print(TEXTE) print(TEXTE)

Heureusement, on peut faire mieux ! Nous allons revoir et compléter la notion de boucle bornée :

1 2 3 4 5 6
# Déclaration des CONSTANTES TEXTE = "J'aime bien les copier coller !" # Programme principal for _ in range(10): print(TEXTE)

Rappels

(RAPPELS) 1.1 Boucle POUR : réaliser plusieurs fois EXACTEMENT la même action

A - Principe

Pour réaliser plusieurs fois exactement la même série d'actions, il suffit d'utiliser une boucle bornée POUR, qu'on déclare à l'aide du mot-clé for en Python.

B - Exemple
1 2 3 4 5 6 7
print("Avant boucle") # Pas tabulée : avant la boucle for _ in range(3): # Déclaration de la boucle print("A") # Tabulée : dans la boucle print("-- B") # Tabulée : dans la boucle print("Après boucle") # Pas tabulée : avant la boucle

Déroulé du programme

L1
L3 - L4 - L5
L3 - L4 - L5
L3 - L4 - L5
L7

Résultat du programme

Avant boucle A -- B A -- B A -- B Après boucle
C - Sémantique
3
for _ in range(3):

Traduction en français : "Réalise 3 fois le bloc d'instructions indentées"

01° Placer le code suivant en mémoire : il affiche le message "C'est parti !" puis 5 fois le message "Et un tour de boucle" sur la console. Une fois la boucle terminée, il affiche "Go !".

Questions

1 2 3 4 5 6
print("C'est parti !") for _ in range(5): print("Et un tour de boucle") print("Fini !")
>>> %Run prog_boucle.py C'est parti ! Et un tour de boucle Et un tour de boucle Et un tour de boucle Et un tour de boucle Et un tour de boucle Fini !

Question

  1. Lancer le programme pour vérifier qu'il fonctionne.
  2. Que trouve-t-on à la fin de la déclaration de la boucle for (et qu'on trouve aussi à la fin d'une déclaration de fonction) ?
  3. Comment indique-t-on à l'interpréteur Python que la ligne 4 fait partie des choses à faire en boucle, et que la ligne 6 sera à faire après avoir fait entièrement la boucle ?
  4. Placer le programme dans Python Tutor et visualiser l'exécution progressive : la boucle devrait être réalisée 5 fois.
  5. Modifier le programme pour qu'il vous affiche 200 fois "Et un tour de boucle".

Complément d'informations Thonny

Thonny permet de placer automatiquement votre script sur Python Tutor à l'aide du menu Exécuter -> Visualiser le script au Python Tutor.

...CORRECTION...

  1. Le programme fonctionne.
  2. Comme pour les déclarations de fonction, la SYNTAXE impose la présence du symbole :.
  3. Comme dans les fonctions, c'est la tabulation (ou 4 espacesà qui indique à l'interpréteur que le bloc d'instructions fait partie de la boucle, ou pas. La ligne 6 est ainsi réalisée après avoir fait la boucle de multiple fois, puisqu'elle n'est pas tabulée.
  4. Il suffit de noter 200 à la place de 5.

02 ✔° Réaliser les deux actions suivantes :

02-A : Placer le code suivant en mémoire : il permet de tracer un triangle en faisant appel à la fonction triangle().

Lancer le code pour visualiser que vous avez bien créé un triangle.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
# Partie Importation import turtle as trt # Partie déclaration des fonctions d'interface def triangle(feutre:trt.Turtle, distance:int, angle:int) -> None: """Fait avancer le crayon de la distance, tourne de l'angle donné. Trois fois.""" feutre.forward(distance) feutre.left(angle) feutre.forward(distance) feutre.left(angle) feutre.forward(distance) feutre.left(angle) # Instructions du programme principal stylo = trt.Turtle() triangle(stylo, 100, 120)

02-B : Remplacer la fonction triangle() par cette version qui utilise une boucle POUR / FOR. Tester pour visualiser qu'on continue bien à obtenir un triange semblable au précédent.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
# Partie Importation import turtle as trt # Partie déclaration des fonctions d'interface def triangle(feutre:trt.Turtle, distance:int, angle:int) -> None: """Fait avancer le crayon de la distance, tourne de l'angle donné. Trois fois.""" for _ in range(3): feutre.forward(distance) feutre.left(angle) # Instructions du programme principal stylo = trt.Turtle() triangle(stylo, 100, 120)

Vous avez dû comprendre le principe : l'association du mot-clé for et du mot-clé in provoque l'apparition d'une boucle : on réalise les lignes 11 et 12 trois fois à cause, visiblement, de la présence de range(3).

03-A° Observer la fonction suivante sans utiliser l'animation :

  • Ecrire la séquence de lignes suivies par l'interpréteur lors d'un appel
  • combien de fois va-t-on réaliser la boucle ?
  • Combien de fois va-t-on réaliser l'instruction "avance" ?
  • Combien de fois va-t-on réaliser l'instruction "tourne à gauche" ?
  • Tester l'animation suivante pour être certain d'avoir compris le déroulé :
1 2 3 4 5 6 7
def exo(feutre:trt.Turtle, distance:int, angle:int) -> None: """Que fait cette fonction ?""" feutre.forward(distance) for _ in range(5): feutre.forward(distance) feutre.left(angle) feutre.forward(distance)

CLIQUEZ ICI POUR VOIR LE DEROULEMENT SEQUENTIEL

...CORRECTION...

L01(on arrive sur cet appel, attribution des valeurs aux paramètres)

L03

L04-L05-L06 (1er tour)

L04-L05-L06 (2e tour)

L04-L05-L06 (3e tour)

L04-L05-L06 (4e tour)

L04-L05-L06 (5e tour)

L07

Notez bien qu'il n'y a pas de return après la ligne 7. Python va donc rajouter return None.

On voit range(5) : la boucle va être réalisée 5 fois.

On va donc "avancer"

  • 1 fois avant la boucle,
  • 5 fois avec les boucles et
  • une fois après la boucle

Soit 7 fois "avance" au total.

Pour l'action "tourne", on ne la réalise qu'une fois par tour de boucle. Il y a donc 5 "tourne" au total.

03-B° Si on utilise la fonction exo(), combien de fois va-t-on faire d'instructions "avance" et combien va-t-on faire d'instructions "tourne à gauche" ? Pour répondre, fournir notamment les lignes suivies par l'interpréteur.

1 2 3 4 5 6 7
def exo(feutre:trt.Turtle, distance:int, angle:int) -> None: """Que fait cette fonction ?""" for _ in range(3): feutre.forward(distance) feutre.left(angle) feutre.forward(distance) feutre.left(angle)

...CORRECTION...

01

03-04-05

03-04-05

03-04-05

06-07

Les lignes 4 et 5 appartiennent à la boucle : on réalise donc trois fois l'action "avance" et "tourne".

Ensuite, on sort de la boucle.

On réalise donc les lignes 6 et 7 et donc "avance" et "tourne" une fois de plus.

En tout, on réalise donc 4 "avance" et 4 "tourne".

Voyons comment tracer plein de formes différentes avec une même fonction en utilisant une variable de boucle.

  • Un triange équilatéral, c'est trois actions "avance et tourne de 120°". On trouve facilement l'angle de 120° en calculant 360° / 3.
  • Un carré, c'est quatre actions "avance et tourne de 90°". On trouve facilement 90° en calculant 360° / 4.
  • ...

04° Compléter la fonction polygone() pour qu'elle réalise les actions suivantes :

  • Calcule l'angle en faisant la division euclidienne de 360 par le nombre de côtés nb voulus : angle = 360 // nb
  • Réalise une boucle POUR où on fait nb fois les actions ci-dessous :
    • Avancer de la longueur longueur
    • Tourner de l'angle angle

La documentation est fournie. A vous de compléter le code.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
# Partie Importation import turtle as trt # Partie déclaration des fonctions def polygone(feutre, nb, longueur): """Crée un polygone à nb cotés, longueur étant la longueur de chaque côté :: param feutre(trt.Turtle) :: un objet-Turtle :: param nb(int) :: le nombre de côtés, PRECONDITION > 2 :: param longueur(int) :: la longueur de chaque côté en pixels. Entier positif. :: return(None) :: trace uniquement la forme """ pass # Instructions du programme principal stylo = trt.Turtle() polygone(stylo, 6, 100)

Vous devriez obtenir ceci après l'appel fourni sur la dernière ligne du programme :

...CORRECTION...

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
# Partie Importation import turtle as trt # Partie déclaration des fonctions d'interface def polygone(feutre, nb, longueur): """Crée un polygone à nb cotés, longueur étant la longueur de chaque côté :: param feutre(trt.Turtle) :: un objet-Turtle :: param nb(int) :: le nombre de côtés, strictement supérieur à 2 :: param longueur(int) :: la longueur de chaque côté en pixels. Entier positif. :: return(None) :: trace uniquement la forme """ angle = 360 // nb for _ in range(nb): feutre.forward(longueur) feutre.left(angle) # Instructions du programme principal stylo = trt.Turtle() polygone(stylo, 6, 100)

On peut maintenant s'amuser et réaliser plein de formes différentes. Imaginons qu'on fasse un appel du type polygone(stylo, 10, 50), il devrait provoquer cela :

Ou tracer un triangle avec un appel du type polygone(stylo, 3, 150), il devrait provoquer cela :

✎ 05° Créer une fonction punition() qui possède deux paramètres :

1 2 3 4 5 6 7 8 9
def punition(ligne_a_copier, nombre_de_fois): """Réalise la punition à la place de l'élève :: param ligne_a_copie(str) :: la ligne qu'on va devoir recopier :: param nombre_de_fois(int) :: le nombre de lignes à faire au total :: return (None) :: ne renvoie rien, "procédure Python". """ pass

Votre fonction devra afficher (afficher donc print()) dans la console la phrase autant de fois que demandé.

Exemple d'utilisation :

>>> punition("Je ne dois pas sortir mon téléphone portable en classe", 3) Je ne dois pas sortir mon téléphone portable en classe Je ne dois pas sortir mon téléphone portable en classe Je ne dois pas sortir mon téléphone portable en classe

Reste un point à voir : qu'est-ce que ce _ qui traîne dans la boucle ?

En réalité, l'underscore _ joue ici le rôle d'une variable particulière qu'on nomme variable de boucle.

Lorsqu'on sait qu'on ne va pas utiliser la valeur de cette variable mais juste réaliser la même action plusieurs fois, la convention Python est de la nommer "underscore", pour montrer que son nom n'a pas d'importance puisqu'on ne l'utilise pas.

Regardons maintenant ce que contient cette variable de boucle lors du déroulé de la boucle. Nous allons la renommer k, plutôt que de la rendre "invisible".

(RAPPELS) 1.2 Boucle POUR : réaliser plusieurs fois PRESQUE la même action

A - Valeurs successives de la variable de boucle

On réalise des actions un peu différentes car utilisant une variable de boucle dont le nom se situe derrière le mot clé for.

for k in range(5):

Sur cet exemple :

  • k est la variable de boucle.
  • k commence à 0
  • k est incrémentée de 1 à chaque tour de boucle.
  • Ainsi, k va prendre les valeurs 0 puis 1 puis 2 puis 3 puis 4.

Attention

  • k n'ira pas jusqu'à 5, c'est une borne exclue.
  • 5 correspond au nombre de tours de boucle effectués : 0-1-2-3-4.
  • La valeur finale de k est 4, obtenue en calculant (5 - 1).
B - Déroulé d'une boucle avec variable de boucle
1 2 3 4 5 6 7
print("Avant boucle") for k in range(3): # Pour k variant de 0 à 2 print("A") # Affiche le string "A" print(k) # Affiche le contenu de k print("Après boucle")

Déroulé du programme

L1
L3(k=0) - L4 - L5
L3(k=1) - L4 - L5
L3(k=2) - L4 - L5
L7

Résultat du programme

Avant boucle A 0 A 1 A 2 Après
C - Sémantique
3
for k in range(3):

Traduction en français : "Pour chaque valeur de k dans [0, 1, 2], réalise le bloc d'instructions indentées"

06° Tester l'animation suivante.

Questions

1 2 3 4 5 6 7
def exo(): """Que fait cette fonction ?""" print("Avant la boucle") for k in range(5): print("Un tour de boucle") print(k) print("Après la boucle")

CLIQUEZ ICI POUR VOIR LE DEROULEMENT SEQUENTIEL

k :

  1. Que vaut la variable de boucle k lors du premier tour de boucle ?
  2. Que vaut la variable de boucle k lors du dernier tour de boucle ?
  3. Quelles sont les valeurs successives prises par la variable de boucle k ?
  4. Combien de valeurs successives (et de tous de boucle) k a-t-elle eu lors du déroulé de la boucle ?

...CORRECTION...

  1. La variable de boucle k commence à 0 lors du premier tour de boucle.
  2. La variable de boucle k finit à 4 lors du dernier tour de boucle.
  3. La variable de boucle k a donc pris les valeurs successives 0 puis 1, puis 2, puis 3 et finalement 4/
  4. Il y a donc eu 5 valeurs différentes et donc 5 tours de boucle.

07° Regarder le programme ci-dessous puis répondre aux questions.

  1. Quelles vont être les valeurs successives prises par la variable de boucle k ?
  2. Combien de cas différents en tout ?
  3. Ecrire le programme équivalent sans boucle qui permettrait d'obtenir le même affichage.
1 2
for k in range(10): print(k)

Si vous n'êtes pas sûr de vous, Python Tutor est votre ami.

...CORRECTION...

La variable de boucle k commence à 0, puis prend la valeur 1, puis prend la valeur 2... jusqu'à arriver à 9.

ATTENTION : on ne va pas jusqu'à 10, on s'arrête juste avant :!

Les différentes valeurs sont : 0 1 2 3 4 5 6 7 8 9

Il y a bien 10 valeurs différentes qui s'étalent de 0 à 9.

1 2 3 4 5 6 7 8 9 10
print(0) print(1) print(2) print(3) print(4) print(5) print(6) print(7) print(8) print(9)

Pour visualiser la valeur de la variable de boucle à l'aide de Turtle, nous pourrions réaliser une boucle où on avance d'une longueur variant avec la variable de boucle, avant de tourner comme avant.

08-A° Lancer le code ci-dessous.

Voici le résultat attendu :

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
# Partie Importation import turtle as trt # Partie déclaration des fonctions def visualiser(feutre:trt.Turtle): """Permet de visualiser la valeur de la variable de boucle""" for k in range(5): feutre.pensize(1+k) feutre.forward(50 + k*50) feutre.left(90) # Instructions du programme principal stylo = trt.Turtle() stylo.speed(1) visualiser(stylo)

Questions après analyse de la fonction

  1. Fournir les lignes suivies par Python lors de l'exécution du programme.
  2. Que valent la largeur du trait et la longueur du trait lors du premier tour de boucle (lorsque k vaut 0)  ?
  3. Que vaut la largeur du trait et la longueur du trait lors du deuxième tour de boucle (lorsque k vaut 1)  ?
  4. Quelle va être la valeur finale de la variable de boucle k ?

...CORRECTION...

  1. Déroulé
    • L03 - L08(déclaration) - L18 - L19 - L20(appel)
    • L08(feutre référence stylo)
    • L10(k=0)-L11-L12-L13
    • L10(k=1)-L11-L12-L13
    • L10(k=2)-L11-L12-L13
    • L10(k=3)-L11-L12-L13
    • L10(k=4)-L11-L12-L13
    • L20(retour)
  2. Lors du premier tour de boucle, k vaut 0.
    • Ligne 11 : on voit que la largeur du trait sera 1 + k, donc 1.
    • Ligne 12 : on voit qu'on avance de 50 + k*50, donc 50.
  3. Lors du deuxième tour de boucle, k vaut 1.
    • Ligne 11 : on voit que la largeur du trait sera 1 + k, donc 2.
    • Ligne 12 : on voit qu'on avance de 50 + k*50, donc 50 + 2*50 ce qui donne 150.
  4. Lors du dernier tour de boucle, k vaut 4.
    • Ligne 11 : on voit que la largeur du trait sera 1 + k, donc 5.
    • Ligne 12 : on voit qu'on avance de 50 + k*50, donc 50 + 4*50 ce qui donne 250.

08-B° On peut utiliser la variable de boucle pour jouer le rôle d'indice dans un tableau. On reprend le même programme en rajoutant simplement cette fois une tableau de couleurs et une modification du crayon à chaque tour de boucle : on va lire une case du tableau en fonction de la valeur de la variable de boucle x.

Vous devriez obtenir ceci maintenant (sans les valeurs de x, je les ai rajouté pour identifier facilement les étapes):

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
# Partie Importation import turtle as trt # Partie déclaration des fonctions def visualiser(feutre:trt.Turtle): """Permet de visualiser la valeur de la variable de boucle""" couleurs = ["grey", "red", "blue", "green", "purple"] for x in range(5): feutre.color(couleurs[x]) feutre.pensize(1+x) feutre.forward(50+x*50) feutre.left(90) # Instructions du programme principal stylo = trt.Turtle() stylo.speed(1) visualiser(stylo)

Question

Expliquer pourquoi le crayon est gris au premier tour de boucle puis rouge au deuxième tour de tour. Un rappel est fourni ci-dessous si vous en avez besoin

Rappel sur la lecture des cases d'un tableau (le type construit list de Python)

>>> t = ["Alice", "Bob"] >>> t[0] 'Alice' >>> t[1] 'Bob' >>> len(t) 2

...CORRECTION...

Lors du premier tour de boucle, x vaut 0.

C'est donc comme si nous avions tapé feutre.color(couleurs[0])

Si nous allons voir le contenu de cette case du tableau, nous voyons qu'elle contient la couleur "grey".

Après évaluation, on a donc feutre.color("grey")

Lors du deuxième tour de boucle, x vaut 1.

C'est donc comme si nous avions tapé feutre.color(couleurs[1])

Si nous allons voir le contenu de cette case du tableau, nous voyons qu'elle contient la couleur "blue".

Après évaluation, on a donc feutre.color("blue")

✌ 08-C° Regardons maintenant comment parvenir à rajouter le texte au dessus du trait à chaque début de tour de boucle.

Pour cela, il faut utiliser la méthode write() sur le stylo (voir ligne 12).

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
# Partie Importation import turtle as trt # Partie déclaration des fonctions def visualiser(feutre:trt.Turtle): """Permet de visualiser la valeur de la variable de boucle""" couleurs = ["grey","red", "blue", "green", "purple"] for x in range(5): feutre.color(couleurs[x]) feutre.write(f"x = {x}") feutre.pensize(1+x) feutre.forward(50+x*50) feutre.left(90) # Instructions du programme principal stylo = trt.Turtle() stylo.speed(1) visualiser(stylo)

Vous devriez maintenant obtenir la même image que celle de la sous-question précédente.

le f-String

On notera qu'on utilise ici un f-String : c'est un string dont les guillemets d'ouverture sont précédés d'un f. A l'intérieur du string, on peut alors placer des accolades {} qui vont jouer un rôle particulier : l'interpéteur Python évalue l'expression fournie entre les accolades et place la valeur obtenue à cet endroit dans le string.

Exemple :

>>> a = "Alice" >>> b = "Bob" >>> c = f"Bonjour à {a} et à {b}" >>> c 'Bonjour à Alice et Bob' >>> n1 = 20 >>> n2 = 20 >>> f"La moyenne est de {n1} et {n2} donne {(n1 + n2) / 2}" 'La moyenne de 20 et 15 donne 17.5'

Question

Après avoir tapé les exemples précédents dans la console (et les avoir réellement compris), modifier la fonction pour qu'elle provoque un affichage : "Sur cette étape, x vaut 0", "Sur cette étape, x vaut 1"...

Nouveautés

1.3 Boucle POUR : utilisation de range()

Visualisation de range sous forme d'un tableau

L'évaluation de range(5) n'est un tableau mais on peut représenter la réponse sous forme d'un tableau à l'aide de la fonction native list().

>>> list(range(5)) [0, 1, 2, 3, 4]

Cela va nous permettre de donner du sens à cette syntaxe.

1.3.1 Un seul argument : borne finale exclue

Lorsqu'on utilise range(10), l'interpréteur Python comprendra :

  • qu'on veut commencer à 0,
  • que la valeur "presque" finale (c'est à dire exclue) est 10 et
  • qu'on incrémentera la variable de boucle de +1 à chaque tour de boucle.

Visualisons cela dans la console. Attention, il faudra appuyer deux fois sur ENTREE (représentée ici par ) pour valider la boucle dans la console.

>>> list(range(10)) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> for k in range(10): print(k) 0 1 2 3 4 5 6 7 8 9
1.3.2 Deux arguments envoyés : valeur initiale, finale exclue

Lorsqu'on utilise range(3, 10), l'interpréteur Python comprendra :

  • qu'on veut commencer à 3,
  • que la valeur "presque" finale (c'est à dire exclue) est 10 et
  • qu'on incrémentera la variable de boucle de +1 à chaque tour de boucle.

Visualisons cela dans la console.

>>> list(range(3, 10)) [3, 4, 5, 6, 7, 8, 9] >>> for k in range(3, 10): print(k) 3 4 5 6 7 8 9
1.3.3 Trois arguments envoyés : initiale, finale exclue, pas

Lorsqu'on utilise range(3, 10, 2), l'interpréteur Python comprendra :

  • qu'on veut commencer à 3,
  • que la valeur "presque" finale (c'est à dire exclue) est 10 et
  • qu'on incrémentera la variable de boucle de +2 à chaque tour de boucle (on dira que le pas est de +2).

Visualisons cela dans la console.

>>> list(range(3, 10, 2)) [3, 5, 7, 9] >>> for k in range(3, 10, 2): print(k) 3 5 7 9

On peut fournir un pas négatif. Ca complique la compréhension de la vraie valeur finale : si la valeur finale est 1 en décroissant, la dernière valeur disponible est donc... 2.

>>> list(range(10, 1, -3)) [10, 7, 4] >>> for k in range(10, 1, -3): print(k) 10 7 4

✌ 09° Expliquer les valeurs successives que vont prendre les variables de boucle a, b et c dans les cas suivants :

>>> for a in range(100): print(a) ??? >>> for b in range(80, 101, 10): print(b) ??? >>> for c in range(100, 49, -10): print(c) ???

10-A° Combien va-t-on dessiner de cercles ? Ecrire les lignes suivies par l'interpréteur.

On considérera que la fonction dessiner_un_cercle() dessine bien un cercle.

1 2 3 4 5
for a in range(5): dessiner_un_cercle() dessiner_un_cercle() dessiner_un_cercle() dessiner_un_cercle()

...CORRECTION 1-2...

Nous allons faire 5 tours de boucles en L1.

Et lors de chacun des tours de boucle, on dessine 4 cercles.

Il va donc y avoir 5 * 4 = 20 cercles.

Déroulé :

L01(a=0) - L02 - L03 - L04 - L05

L01(a=1) - L02 - L03 - L04 - L05

L01(a=2) - L02 - L03 - L04 - L05

L01(a=3) - L02 - L03 - L04 - L05

L01(a=4) - L02 - L03 - L04 - L05

10-B° Combien va-t-on dessiner de cercles ?

1 2 3
for a in range(5): for b in range(4): dessiner_un_cercle()

...CORRECTION 1-2...

Encore 20. Pourquoi ?

A chaque fois qu'on réalise entiérement la boucle présente en L2, on dessine 4 cercles.

On réalise la boucle présente en L1 5 fois. Or pendant chaque tour de la boucle 1, on exécute 4 fois la boucle 2. Donc 5*4 = 20 cercles.

Déroulé

L01(a=0) - L02(b=0) - L03- L02(b=1) - L03- L02(b=2) - L03- L02(b=3) - L03

L01(a=1) - L02(b=0) - L03- L02(b=1) - L03- L02(b=2) - L03- L02(b=3) - L03

L01(a=2) - L02(b=0) - L03- L02(b=1) - L03- L02(b=2) - L03- L02(b=3) - L03

L01(a=3) - L02(b=0) - L03- L02(b=1) - L03- L02(b=2) - L03- L02(b=3) - L03

L01(a=4) - L02(b=0) - L03- L02(b=1) - L03- L02(b=2) - L03- L02(b=3) - L03

11° Que va afficher ce programme ? Expliquer l'ordre de l'affichage obtenu.

1 2 3
for a in range(2, 9, 3): for b in range(10, 101, 20): print(f"a = {a} et b = {b}")

...CORRECTION 1-2...

La variable de boucle a va prendre les valeurs 2, 5, 8.

Lors du premier tour de boucle, la valeur de a est donc 2.

La variable de boucle b va prendre les valeurs 10, 30, 50, 70, 90. Soit 5 tours de boucles différents.

On va donc obtenir ceci lors du premier tour de boucle sur a :

a = 2 et b = 10 a = 2 et b = 30 a = 2 et b = 50 a = 2 et b = 70 a = 2 et b = 90

Ensuite, on va revenir sur un nouveau tour de boucle pour a qui devient 5.

a = 5 et b = 10 a = 5 et b = 30 a = 5 et b = 50 a = 5 et b = 70 a = 5 et b = 90

Enfin, on fait le dernier tour de boucle pour a qui devient 8.

a = 8 et b = 10 a = 8 et b = 30 a = 8 et b = 50 a = 8 et b = 70 a = 8 et b = 90

✎ 12° Expliquer clairement pourquoi le programme suivant crée exactement 16 cercles. Pour cela, il "suffit" de savoir répondre aux question suivantes (si vous n'y arrivez pas seul, Python Tutor n'est pas votre ami car il n'intègre pas Turtle !) :

  1. Combien de fois cercles() (avec un s) va être appelée pendant l'exécution de la fonction dessin() ?
    • Autrement dit : combien de valeurs différentes va prendre la variable de boucle angle de la ligne 18 ?
  2. Lors des appels à cercles(), comprendre ce que vont recevoir les paramètres rmax, rmin et pas.
  3. Lors de chacun des appels à cercles() (avec un s) combien d'appels à cercle() (sans s) ?
    • Autrement dit : combien de valeurs différentes va prendre la variable de boucle rayon de la ligne 13 ?

Voici le programme utilisé pour réaliser ce dessin.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
import turtle as trt def cercle(rayon:int, angle:int): """Fonction qui trace UN cercle.""" feutre = trt.Turtle() feutre.color("red") feutre.pensize(5) feutre.setheading(angle) feutre.circle(rayon, 360) def cercles(rmin:int, rmax:int, pas:int, angle:int): """Fonction qui trace DES cercles en utilisant... cercle()""" for rayon in range(rmin, rmax, pas): cercle(rayon, angle) def dessin(): """Fonction qui trace un dessin en utilisant cercles()""" for angle in range(0, 360, 90): cercles(50, 150, 25, angle) dessin()

Pour info (ça ne sert à rien pour résoudre la question), la méthode setheading() permet de forcer la tortue à regarder dans une direction précise (qu'on fournit sous forme d'un angle : 0° veut dire de regarder vers la droite, 180° vers la gauche...).

1.4 Boucle POUR : boucle BORNEE

Les boucle POUR sont des boucles bornées : on ne peut pas boucler à l'infini puisqu'on pourrait prévoir à l'avance combien de fois le bouclage sera réalisé.

2 - Sommes et concaténations successives

Voici l'une des actions fondamentales à savoir faire : additionner des nombres et récupérer la somme.

2.1 Boucle POUR : somme avec additions successives

Nous voudrions faire la somme de plusieurs nombres 0 + 1 + 2 + 3 + 4 + 5 + 6 ... + 1000 jusqu'à un entier final au choix (1001 sur l'exemple).

Nous allons calculer la somme par additions successives, en écrasant la version précédente par la nouvelle version.

La signature de l'addition d'entiers' est int + int -> int.

Cela reviendrait à faire ceci à la main (et jusqu'à 1000, ça risque d'être long à taper...) :

1 2 3 4 5 .. 1001
somme = 0 somme = somme + 1 somme = somme + 2 somme = somme + 3 somme = somme + 4 ... somme = somme + 1000

Plutôt que de tout faire à la main, utilisons une boucle dont la variable de boucle se nommerait nombre.

1 2 3
somme = 0 # Initialisation du compteur for nombre in range(1, 1001): # Pour chaque nombre entier de 1 à 1000 somme = somme + nombre # Incrémente somme avec ce nombre

Attention à la phase d'initialisation de la ligne 1. Elle est très importante et nous allons la retrouver très souvent cette année.

✎ 13-A° On veut réaliser une fonction somme() qui renvoie la somme des n premiers entiers.

Par exemple, somme(4) doit renvoyer la somme de 0+1+2+3+4, soit 10.

Nous allons donc faire cela en boucle.

On crée une variable de stockage qu'on nommera s.

A chaque étape, on va donc rajouter la valeur de la valeur de boucle à la variable s et remettre le résultat dans la variable s.

On aura ainsi :

Initialisation : s = 0

Premier tour de boucle : s = s + 0, soit s = 0

Deuxième tour de boucle : s = s + 1, soit s = 1

Troisième tour de boucle : s = s + 2, soit s = 3

Quatrième tour de boucle : s = s + 3, soit s = 6

...

Compléter la fonction somme() pour qu'elle fonctionne correctement :

1 2 3 4 5 6
def somme(n:int) -> int: """Renvoie la somme des entiers de 1 jusqu'à n INCLUS""" s = ... for x in range(..., ..., ...): s = s + ... return ...
>>> somme(3) 6 >>> somme(4) 10 >>> somme(5) 15 >>> somme(6) 21

Tant que la fonction ne renvoie pas cela, c'est que votre fonction ne fonctionne pas !

✌ 13-B° Vous décidez d'organiser une fête, payante.

Le premier arrivé doit payer un euro, le deuxième 2 euros, le troisième 3 euros...

Vous avez eu 600 clients avant que plus personne n'accepte de payer.

Quelle somme d'argent avez-vous récolté ?

2.2 - Boucle POUR : concaténations successives

Nous voudrions créer une chaîne de caractères contentant "0 1 2 3 4 5 6 ... 1000" jusqu'à un entier final au choix (1000 sur l'exemple).

La signature de la concaténation de strings est str + str -> str.

Cela reviendrait à faire ceci à la main (et jusqu'à 1000, ça risque d'être long à taper...) :

1 2 3 4 5 .. 1002
chaine = "" chaine = chaine + str(0) + " " # on obtient "0 " chaine = chaine + str(1) + " " # on obtient "0 1 " chaine = chaine + str(2) + " " # on obtient "0 1 2" chaine = chaine + str(3) + " " # on obtient "0 1 2 3 " ... chaine = chaine + str(1000) + " "

Utilisons une boucle dont la variable de boucle se nommerait nombre.

1 2 3
chaine = "" for nombre in range(1001): chaine = chaine + str(nombre) + " "

Attention à la phase d'initialisation de la ligne 1. Elle est très importante et nous allons la retrouver très souvent cette année.

14° Lancer ce programme et vérifier que la chaine obtenue est correcte. Répondre ensuite aux questions proposées.

1 2 3
chaine = "" for nombre in range(1001): chaine = chaine + str(nombre) + " "
>>> chaine '0 1 2 3 4 5 6 7 8 9 ... 1000'

Question A : dans ce programme de concaténations successives, que contient chaine avant le premier tour de boucle ? Comment se nomme la phase correspondant à la ligne 1 ?

1 2 3
chaine = "" for nombre in range(1001): chaine = chaine + str(nombre) + " "

Question B : expliquer l'erreur obtenue si on ne place pas la ligne 1 ?

1 2 3
for nombre in range(1001): chaine = chaine + str(nombre) + " "
chaine = chaine + str(nombre) + " " NameError: name 'chaine' is not defined

Question C : pourquoi un humain parviendrait-il à exécuter cela si on lui donner des instructions en oubliant la ligne 1 ?

...CORRECTION...

Question A

La chaine contient une première valeur d'initialisation.

Question B

On voit que l'initialisation est indispensable car, sinon, python ne serait pas en capacité d'évaluer chaine = chaine + .... Puisqu'il commence l'évaluation à droite, il ne connaît pas chaine et ne peut donc pas l'évaluer.

Question C

L'humain a un avantage énorme sur la machine : il peut remplir les trous avec son intuition et sa capacité d'analyse. Il est libre d'interpréter à sa guise et de donner du sens à l'instruction : il manque une première valeur ? Ok, prenons un caractère vide. La machine ne fait qu'exécuter, sans réflexion ni analyse. C'est juste une machine.

15° Fournir deux programmes permettant d'obtenir les deux chaînes ci-dessous.

>>> chaine '10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 '
>>> chaine '100 95 90 85 80 75 70 65 60 55 50 45 40 35 30 25 20 15 10 '

...CORRECTION...

1 2 3
chaine = "" for nombre in range(10, 41, 2): chaine = chaine + str(nombre) + " "
1 2 3
chaine = "" for nombre in range(100, 9, -5): chaine = chaine + str(nombre) + " "

3 - Obtenir les indices avec une boucle Pour

Il est possible d'utiliser une boucle for de façon à lire ou modifier une à une toutes les "cases" d'un type construit. Pour cela, il faut utiliser :

  • Leurs indices dans les tableaux, les strings et les tuples
  • Leurs clés dans les dictionnaires
(RAPPELS) 3.1 STRING : accéder à toutes les cases

On utilise une boucle for .. in couplée à la fonction len() pour connaître l'indice i limite.

Ainsi avec "bonjour", on a 7 caractères d'indices 0 à 6.

1 2 3 4
s = "bonjour" for i in range(len(s)): # Pour chaque indice possible dans s print(s[i]) # Affiche le contenu de la case i

Ce programme est équivalent à ceci :

1 2 3 4 5 6 7 8 9
s = "bonjour" print(s[0]) print(s[1]) print(s[2]) print(s[3]) print(s[4]) print(s[5]) print(s[6])

Ils affichent l'un et l'autre ceci dans la console :

b o n j o u r
(RAPPELS) 3.2 TABLEAU STATIQUE : accéder à toutes les cases

On utilise une boucle for .. in couplée à la fonction len() pour connaitre l'indice i limite.

Ainsi avec [20, 8, 18, 12], on a 4 notes d'indices 0 à 3.

1 2 3 4
t = [20, 8, 18, 12] for i in range(len(t)): # Pour chaque indice possible dans t print(t[i]) # Affiche le contenu de la case i

Ce programme est équivalent à ceci :

1 2 3 4 5 6
t = [20, 8, 18, 12] print(t[0]) print(t[1]) print(t[2]) print(t[3])

Ils affichent l'un et l'autre ceci dans la console :

20 8 18 12
(RAPPELS) 3.3 n-UPLET : accéder à toutes les cases

On utilise une boucle for .. in couplée à la fonction len() pour connaitre l'indice i limite.

Ainsi avec ("In Borderland", "Alice", 18, True ), on a 4 éléments d'indices 0 à 3.

1 2 3 4
eleve = ("In Borderland", "Alice", 18, True) for i in range(len(eleve)): # Pour chaque indice possible dans eleve print(eleve[i]) # Affiche le contenu de la case i

Ce programme est équivalent à ceci :

1 2 3 4 5 6
eleve = ("In Borderland", "Alice", 18, True) print(eleve[0]) print(eleve[1]) print(eleve[2]) print(eleve[3])

Ils affichent l'un et l'autre ceci dans la console :

'In Borderland' 'Alice' 18 True

16° Compléter la fonction somme_tableau() qui renvoie la somme des entiers POSITIFS contenus dans le tableau.

Documentation rapide

L'indication de type t:list[int] indique que t doit être un tableau contenant des integers.

1 2 3 4 5 6 7
def somme_tableau(t:list[int]) -> int: """Renvoie la somme des entiers dans le tableau t""" s = ... for i in ...: if t[i] ... 0: s = ... return ...
>>> somme_tableau([10, 20, -50, 30]) 60

...CORRECTION...

1 2 3 4 5 6 7
def somme_tableau(t:list[int]) -> int: """Renvoie la somme des entiers dans le tableau t""" s = 0 # Initialisation d'un compteur for i in range(len(t)): # Pour chaque indice possible dans t if t[i] >= 0: # Si le contenu de la case i est positif s = s + t[i] # On incrémente s de la valeur dans la case return s # APRES avoir fait tous les tours
3.4 Boucle POUR : somme d'un tableau

1 2 3 4 5 6
def somme_tableau(t:list[int]) -> int: """Renvoie la somme des entiers dans le tableau t""" s = 0 # Initialisation d'un compteur for i in range(len(t)): # Pour chaque indice possible dans t s = s + t[i] # On incrémente s de la valeur dans la case return s # APRES avoir fait tous les tours

L'un des intérêts d'obtenir les indices est notamment de pouvoir modifier toutes les cases correspondantes d'un tableau.

(RAPPELS) 3.5 TABLEAU STATIQUE : muable en Python (modification possible)

En Python, les tableaux sont muables (ou mutables en anglais) : on peut modifier le contenu d'une case après la création du tableau.

Imaginons qu'on ai oublié des points à Bob (l'élève d'indice 1) : il n'a pas 8 mais 11 finalement. Voici comment nous pourrions modifier le tableau APRES création

Indice 0 1 2 3 >>> notes = [20, 8, 18, 12] >>> notes[1] = 11 >>> notes [20, 11, 18, 12]

Ce n'est pas une affectation sur le tableau lui-même : l'affectation est faite sur l'une des cases notes[i] du tableau.

17° Lancer le programme suivant, comprendre ce qu'il réalise pour compléter les commentaires pour donner la signification en français de chacune des lignes.

1 2 3 4 5 6 7 8 9 10
t = [5, 2, -7, 15, -10] # ? print("Avant la boucle") print(t) # ? for i in range(len(t)): # ? if t[i] < 0: # ? t[i] = -t[i] # ? print("Après la boucle") print(t) # ?

...CORRECTION...

1 2 3 4 5 6 7 8 9 10
t = [5, 2, -7, 15, -10] # Création du tableau t print("Avant la boucle") print(t) # Affichage sur la console du tableau for i in range(len(t)): # Pour chaque indice possible dans le tableau if t[i] < 0: # Si le contenu de la case i est négatif t[i] = -t[i] # On remplit la case par son opposé, positif donc print("Après la boucle") print(t) # Affichage sur la console du tableau

4 - Obtenir les clés avec une boucle Pour

(RAPPELS) 4.1 DICTIONNAIRE : accéder à toutes les cases

On utilise une boucle for .. in mais on ne peut pas la coupler à la fonction len puisqu'un dictionnaire possède des clés, pas des indices.

Voici la manière usuelle d'obtenir les clés une par une.

1 2 3 4
ds = {"Alice": 13, "Bob": 8, "Charlie": 12} for cle in ds.keys(): # Pour chaque cle possible dans ds print(ds[cle]) # Affiche la valeur associée à cette clé

Ce programme est équivalent à ceci :

1 2 3 4 5
ds = {"Alice": 13, "Bob": 8, "Charlie": 12} print(ds["Alice"]) print(ds["Bob"]) print(ds["Charlie"])

Ils affichent l'un et l'autre ceci dans la console :

13 8 12

18° Compléter la fonction somme_dict() qui renvoie la somme des entiers POSITIFS contenus dans le dictionnaire.

Documentation rapide

L'indication de type d:dict[(str, int)]): indique que d doit être un dictionnaire dont les clés sont des strings et les valeurs sont des integers.

1 2 3 4 5 6 7
def somme_dict(d:dict[(str, int)]) -> int : """Renvoie la somme des entiers dans le dictionnaire d""" s = ... for cle in ...: if ... >= ...: s = ... return s
>>> ds = {"Alice":10, "Bob":20, "Charlie":5} >>> somme_dict(ds) 35

...CORRECTION...

1 2 3 4 5 6 7
def somme_dict(d:dict[(str, int)]): """Renvoie la somme des entiers dans le dictionnaire d""" s = 0 # Initialisation d'un compteur for cle in d.keys(): # Pour chaque clé du dictionnaire d if d[cle] >= 0: # Si la valeur associée à cette clé est positive s = s + d[cle] return s
4.2 Boucle POUR : somme d'un dictionnaire

1 2 3 4 5 6 7
def somme_dict(d:dict[(str, int)]) -> int: """Renvoie la somme des entiers dans le dictionnaire d""" s = 0 # Initialisation d'un compteur for cle in d.keys(): # Pour chaque clé du dictionnaire d s = s + d[cle] return s

L'un des intérêt d'avoir connaissance des clés une par une est de pouvoir modifier les cases du dictionnaire.

(RAPPELS) 4.3 DICTIONNAIRE : muable en Python (modification possible)

En Python, les dictionnaires sont muables (ou mutables en anglais) : on peut modifier le contenu d'une case après la création du dictionnaire.

Modification d'un couple existant

Imaginons qu'on ai oublié des points à Bob : il n'a pas 8 mais 11 finalement. Voici comment nous pourrions modifier le tableau APRES création

>>> {"Alice": 13, "Bob": 8, "Charlie": 12} >>> notes["Bob"] 8 >>> notes["Bob"] = 11 >>> notes["Bob"] 11 >>> notes {'Alice': 13, 'Bob': 11, 'Charlie': 12}

Notez bien que ce n'est pas une affectation sur le dictionnaire : l'affectation est faite sur l'un des contenus des associations clé-valeur du dictionnaire, pas sur le dictionnaire lui-même.

Rajout d'un nouveau couple

On peut rajouter de la même façon un couple qui n'existe pas encore.

Imaginons un nouvel élève nommé David qui a eu 15.

>>> {"Alice": 13, "Bob": 11, "Charlie": 12} >>> notes["David"] = 15 >>> notes {'Alice': 13, 'Bob': 11, 'Charlie': 12, 'David': 15}

19° Lancer le programme suivant, comprendre ce qu'il réalise pour compléter les commentaires pour donner la signification en français de chacune des lignes.

1 2 3 4 5 6 7 8 9 10
d = {"A":12, "B":20, "C":7} # ? print("Avant la boucle") print(d) # ? for cle in d.keys(): # ? if (d[cle] % 2) == 0: # ? d[cle] = d[cle] + 1 # ? print("Après la boucle") print(d) # ?

...CORRECTION...

1 2 3 4 5 6 7 8 9 10
d = {"A":12, "B":20, "C":7} # Création du dictionnaire d print("Avant la boucle") print(d) # Affichage sur la console du dictionnaire for cle in d.keys(): # Pour chaque clé possible dans le dictionnaire if (d[cle] % 2) == 0: # Si la valeur (le contenu de la case) est paire d[cle] = d[cle] + 1 # On rajoute 1 à la case print("Après la boucle") print(d) # Affichage sur la console du dictionnaire

5 - Obtenir directement le contenu

La syntaxe permettant d'accéder à tous les indices ou toutes les clés est un peu lourde.

Or, elle n'est indispensable que si on désire MODIFIER le contenu de la structure.

Si on désire simplement lire le contenu, on peut utiliser une autre syntaxe qui permet d'accéder directement au contenu, sans passer par les étiquettes (indices ou clés).

5.1 STRING : accéder à toutes les VALEURS

Si on désire uniquement LIRE les caractères d'un string, on PEUT utiliser une boucle for ... in en l'associant directement au nom du string.

La variable de boucle va alors contenir les caractères un par un, et non plus l'indice du caractère.

Ainsi avec "bonjour", on a 7 caractères.

1 2 3 4
s = "bonjour" for c in s: # Pour chaque caractère possible dans s print(c) # Affiche le caractère c

Ce programme est équivalent à ceci :

1 2 3 4 5 6 7 8 9
s = "bonjour" print(s[0]) print(s[1]) print(s[2]) print(s[3]) print(s[4]) print(s[5]) print(s[6])

Ils affichent l'un et l'autre ceci dans la console :

b o n j o u r
5.2 n-UPLET : accéder à toutes les VALEURS

Si on désire uniquement LIRE les valeurs d'un n-uplet, on PEUT utiliser une boucle for ... in en l'associant directement au nom du n-uplet.

Ainsi avec ("In Borderland", "Alice", 18, True ), on a 4 valeurs.

1 2 3 4
eleve = ("In Borderland", "Alice", 18, True) for v in eleve: # Pour chaque valeur possible dans eleve print(v) # Affiche la valeur

Ce programme est équivalent à ceci :

1 2 3 4 5 6
eleve = ("In Borderland", "Alice", 18, True) print(eleve[0]) print(eleve[1]) print(eleve[2]) print(eleve[3])

Ils affichent l'un et l'autre ceci dans la console :

'In Borderland' 'Alice' 18 True
5.3 TABLEAU STATIQUE : accéder à toutes les VALEURS

5.3.1 Syntaxe

Si on désire uniquement LIRE les valeurs d'un tableau, on PEUT utiliser une boucle for ... in en l'associant directement au nom du tableau.

Ainsi avec [20, 8, 18, 12], on a 4 notes.

1 2 3 4
t = [20, 8, 18, 12] for note in t: # Pour chaque valeur possible dans t print(note) # Affiche la valeur

Ce programme est équivalent à ceci :

1 2 3 4 5 6
t = [20, 8, 18, 12] print(t[0]) print(t[1]) print(t[2]) print(t[3])

Ils affichent l'un et l'autre ceci dans la console :

20 8 18 12
5.3.2 Impossible de MODIFIER avec cette boucle

Notez bien qu'on ne peut que LIRE.

Le code suivant ne modifie pas le tableau.

3 4
for note in t: # Pour chaque valeur possible dans t note = note + 5 # Ne modifie absolument pas le contenu du tableau !
5.4 DICTIONNAIRE : accéder à toutes les VALEURS

5.4.1 Syntaxe

Si on désire uniquement LIRE les valeurs d'un dictionnaire, on PEUT utiliser une boucle for ... in en utilisant la méthode values() sur le dictionnaire.

1 2 3 4
ds = {"Alice": 13, "Bob": 8, "Charlie": 12} for v in ds.values(): # Pour chaque valeur possible dans ds print(v) # Affiche la valeur lue sur ce tour de boucle

Ce programme est équivalent à ceci :

1 2 3 4 5
ds = {"Alice": 13, "Bob": 8, "Charlie": 12} print(ds["Alice"]) print(ds["Bob"]) print(ds["Charlie"])

Ils affichent l'un et l'autre ceci dans la console :

13 8 12
5.4.2 Impossible de MODIFIER avec cette boucle

Notez bien qu'on ne peut que LIRE.

Le code suivant ne modifie pas le contenu du dictionnaire.

3 4
for v in ds.values(): # Pour chaque valeur possible dans ds v = v + 5 # Ne modifie pas le contenu du dictionnaire !

20° Modifier la fonction somme() pour qu'elle réalise bien la somme des éléments du tableau. On impose l'utilisation de la lecture directe des valeurs plutôt que de passer par les indices.

1 2 3 4 5 6 7 8 9 10 11 12 13
t = [10, 20, 30] def somme(t:list[int]) -> int: """Renvoie la somme des valeurs contenues dans le tableau""" s = ... # Initialisation de la variable somme for v in ...: # Pour chaque valeur du tableau ... = ... + ... # Incrémente s de cette valeur return ... # Après avoir fait toute la boucle print(somme(t))

...CORRECTION...

1 2 3 4 5 6 7 8 9 10 11 12 13
t = [10, 20, 30] def somme(t:list[int]) -> int: """Renvoie la somme des valeurs contenues dans le tableau""" s = 0 # Initialisation de la variable somme for v in t: # Pour chaque valeur du tableau s = s + v # Incrémente s de cette valeur return s # Après avoir fait toute la boucle print(somme(t))

6 - Mode DEBUG de Thonny

REMARQUE

Cette partie sera à faire ensemble : c'est un ensemble de manipulation. Ce n'est pas compliqué mais lire les manipulations à faire est plus difficile que de les faire directement.

Si vous n'utilisez pas Thonny, vous pouvez passer à la partie suivante.

Le logiciel Thonny possède une fonctionnalité que vous avez déjà rencontré  le mode PAS A PAS. Il permet d'exécuter du code ligne par ligne. Nous allons voir comment il fonctionne sur les boucles (et plus généralement les blocs d'instructions).

DEBUG 1° Placer ce code dans Thonny SANS LE LANCER. Ouvrir l'onglet VIEW-VARIABLES pour observer les variables.

1 2 3
chaine = "" for nombre in range(2, 10, 2): chaine = chaine + str(nombre) + " "

Pour lancer le mode DEBUG / PAS A PAS, il faut appyer sur le bouton "BUG" situé à DROITE de la flèche verte permettant juste de lancer le script.

Appuyer sur ce bouton et suivre les indications ci-dessous.

Vous devriez obtenir la première ligne en surbrillance : Thonny attend que vous validiez cette ligne. Pour l'instant, il n'a rien fait.

Pour lui demander d'exécuter cette ligne, il faut appuyer sur le bouton qui se trouve à droite du BUG et qui se nomme STEP OVER :

DEBUG 2° Appuyer sur le bouton STEP OVER.

On constate alors bien l'apparition d'une variable chaine ne contenant rien.

On voit que Thonny attend patiemment qu'on lui donne l'autorisation d'exécuter ce bloc en surbrillance.

Or, nous voulons voir comment s'exécute ce bloc pas à pas, nous ne voulons pas l'exécuter d'un coup. Pour cela, il va encore falloir appuyer sur un autre bouton : le bouton STEP INTO, qui permet de rentrer dans l'évaluation du bloc.

DEBUG 3° Appuyer sur le bouton STEP INTO.

On rentre bien dans le bloc et Thonny vous demande s'il peut commencer à évaluer l'ensemble des valeurs qu'il va devoir générer une à une :

DEBUG 4° Appuyer sur le bouton STEP OVER pour autoriser Thonny à exécuter cette évaluation (sans rentrer dans le détail de l'évaluation)

On obtient alors bien la première valeur de la suite, à savoir 2.

DEBUG 5° Appuyer encore sur le bouton STEP OVER pour autoriser Thonny à exécuter cette évaluation (sans rentrer dans le détail de l'évaluation)

On voit à droite qu'il a créé une variable nombre valant 2.

Il attend donc de pouvoir exécuter la ligne en surbrillance.

DEBUG 6° Valider chacune des instructions pour voir la création progressive de la chaîne de caractères.

Voici le résultat :

Lorsqu'on validera cette ligne, Python va donc concaténer '2 ' + '4' + ' ' qui sera évaluée à '2 4 ' et placée à nouveau dans la variable chaine. Résultat en image ci-dessous :

Lorsqu'on validera cette ligne, Python va donc concaténer '2 4 ' + '6' + ' ' qui sera évaluée à '2 4 6 ' et placée à nouveau dans la variable chaine. Résultat en image ci-dessous :

Nous arrivons ici à la dernière instruction puisque la variable de boucle ne pourra plus augmenter de 2. La chaîne de caractères va donc subir une dernière concaténation avant d'arriver à son état final.

Lorsqu'on validera cette ligne, Python va donc concaténer '2 4 6 ' + '8' + ' ' qui sera évaluée à '2 4 6 8 ' et placé à nouveau dans la variable chaine. Résultat en image ci-dessous :

Nous reviendrons régulièrement sur ce mode DEBUG. Dès qu'on change vous semble étrange, pensez à l'utiliser : cela vous permet de voir ce que Python fait VRAIMENT avec votre code.

7 - DEBUG avec Pythontutor

Vous pouvez également faire la même chose avec le site Pythontutor bien entendu.

DEBUG 7° Placer ce code sur le site Pythontutor. Il faut

  1. cliquer sur Start visualizing your code now,
  2. placer votre code.
  3. cliquer sur Visualize Execution
  4. avancer instruction par instruction avec Next
1 2 3
chaine = "" for nombre in range(2, 10, 2): chaine = chaine + str(nombre) + " "

Au final, vous arriverez bien entendu au même point qu'avec Thonny, à savoir ceci :

8 - FAQ

Rien pour le moment

Voilà pour les boucles bornées qui permettent donc de faire plusieurs fois la même chose, ou presque.

Reste à voir les boucles non bornées.

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