Vidéo 18 : La boucle for

\(\newcommand{\ds}{\displaystyle}\) \(\newcommand{\Frac}{\ds\frac}\) \(\renewcommand{\r}{\mathbb{ R}}\) \(\newcommand{\C}{\mathbb{ C}}\) \(\newcommand{\n}{\mathbb{ N}}\) \(\newcommand{\z}{\mathbb{ Z}}\) \(\newcommand{\Q}{\mathbb{ Q}}\) \(\newcommand{\N}{\mathbb{ N}}\) \(\newcommand{\n}{\mathbb{ N}}\) \(\newcommand{\ol}{\overline}\) \(\newcommand{\abs}[1]{\left| \,{#1} \right|}\) \(\newcommand{\pv}{\;;\;}\) \(\newcommand{\ens}[1]{\left\{ {#1} \right\}}\) \(\newcommand{\mens}[1]{\setminus\left\{ {#1} \right\}}\) \(\newcommand{\Par}[1]{\left({#1}\right)}\)

Vidéo 18 : La boucle for

Boucle for : introduction

Le code suivant présente un exemple d’utilisation d’une boucle for :

for.py

1
2
3
for i in range(0, 4):
    print("Bonjour !")
    print("---------")
 4
 5
 6
 7
 8
 9
10
11
Bonjour !
---------
Bonjour !
---------
Bonjour !
---------
Bonjour !
---------

Les lignes 1-3 constituent une instruction for. On observe (lignes 4-11) que le message Bonjour ! suivi du séparateur --------- est affiché 4 fois. Si on changeait la valeur 4 à la ligne 1 en la valeur 5 le message serait répété 5 fois.

Ici, la boucle for a permis de répéter une action un certain nombre de fois.

Déroulement d’une instruction for

  • À la ligne 1, la présence de range(0, 4) permet d’itérer sur les entiers de 0 à 4, l’entier 4 étant exclu : 0, 1, 2 et 3. Les entiers vont être générés les uns à la suite des autres.
  • Quand la boucle for commence, l’indice i vaut le premier élément généré (ici 0).
  • L’exécution entre ensuite dans la ligne 2, effectue l’action d’affichage puis idem à la ligne 3
  • Une fois les deux affichages effectués, l’exécution revient à la ligne 1. Comme pour l’instant i = 0, il reste encore des entiers à générer, donc, le principe même de l’instruction for veut que i passe à l’élément suivant, ie i = 1 puis les instructions d’affichage des lignes 2-3 s’exécutent à nouveau.
  • L’exécution se poursuit ainsi jusqu’à ce que i passe de 2 à 3. Lorsque i vaut 3, un affichage se fait encore et lorsque l’exécution repasse ligne 1, tous les entiers ont été générés : la conséquence est que la boucle s’arrête.

Édition d’une boucle for

On reprend le code for.py, on détaille la syntaxe d’une boucle for et le vocabulaire associé :

for.py

1
2
3
for i in range(0, 4):
    print("Bonjour !")
    print("---------")
  • Ligne 1 : for et in sont des mots-clés de Python et sont obligatoires à toute boucle for.
  • Ligne 1 : i est la variable de contrôle de la boucle for. D’autres noms fréquents de variables sont j, k mais tout nom de variable comme toto conviendrait. Ici, la variable de contrôle parcourt la succession des entiers générés par range(0,4).
  • Ligne 1 : le séparateur deux-points (:) à la fin est obligatoire
  • Ligne 1 : range est une fonction built-in du langage Python qui sert à générer des entiers consécutifs.
  • Ligne 1 : la partie qui commence à for jusqu’aux deux-points est appelé l”en-tête de la boucle for
  • Lignes 2-3 : le corps de la boucle. Les instructions du corps de la boucle for sont celles qui vont être répétées tant que i est généré. Ce n’est pas le cas ici mais en général, le corps de la boucle dépend de la variable i. Le corps de la boucle for est dans l’immense majorité des cas, situé une ligne sous l’en-tête, autrement dit un saut de ligne dans le code-source est effectué après l’en-tête.
  • Lignes 2-3 : le corps de la boucle for est toujours indenté et suit la règle générale d’indentation en Python.
  • Lignes 1-3 : les trois lignes constituent une seule et même instruction, dite « instruction for ».

Le terme de boucle vient du fait que lorsque l’exécution est parvenue à la fin du corps de la boucle, l’exécution retourne à l’en-tête de la boucle.

Action qui dépend de la variable de la boucle

Dans le code for.py, l’action effectuée à chaque étape du parcours de la liste ne dépendait pas de la variable i. En fait, assez souvent, l’action effectuée dans le corps de la boucle dépendra de la variable de contrôle. Voici un exemple :

1
2
for i in range(0, 5):
    print("Message n°", i+1, ":", "Bonjour !")

qui affiche

1
2
3
4
5
Message n° 1 : Bonjour !
Message n° 2 : Bonjour !
Message n° 3 : Bonjour !
Message n° 4 : Bonjour !
Message n° 5 : Bonjour !

On observe que chaque message affiché est différent du précédent par le numéro qu’il affiche : en effet, le corps de la boucle (ligne 2) dépend de i qui varie à chaque tour de boucle.

Répéter une action \(n\) fois avec une boucle for

La boucle for et la fonction range permettent typiquement de répéter une action n fois où n est fixé avant le démarrage de la boucle.

Par exemple, soit à afficher un carré de côté 10 comme ci-dessous :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
* * * * * * * * * *
* * * * * * * * * *
* * * * * * * * * *
* * * * * * * * * *
* * * * * * * * * *
* * * * * * * * * *
* * * * * * * * * *
* * * * * * * * * *
* * * * * * * * * *
* * * * * * * * * *

L’affichage consiste en la répétition 10 fois de l’affichage d’une ligne de la forme

1
* * * * * * * * * *

où les étoiles sont séparés par une espace.

Le code Python pourrait être :

1
2
3
z="* * * * * * * * * *"
for i in range(10):
    print(z)

De même, soit à afficher les 10 premiers multiples de 5 en commençant par 75 :

\(75\), \(75 +5=80,\) \(75+10=85\), etc.

Donc, un code répondant à la question est le suivant :

1
2
3
d = 75
for i in range(10):
    print(d + 5 * i)
 4
 5
 6
 7
 8
 9
10
11
12
13
75
80
85
90
95
100
105
110
115
120
  • Ligne 2 : typiquement, on utilise range(10) pour exprimer qu’une action va être exécutée 10 fois. Le nombre de répétitions (ici 10) est connu avant d’effectuer la boucle for.
  • Ligne 3 : l’action (d’afficher le multiple) est à effectuer 10 fois.

Règle : Si un programme répète une action et si le nombre de répétitions à effectuer est connu à l’avance, le programme utilise une boucle for avec la syntaxe suivante :

1
2
for i in range(n):
    # action a coder ICI

Itérer sur des entiers consécutifs

La fonction built-in range permet de générer automatiquement des entiers consécutifs, comme les entiers 6, 7, 8 et 9 :

1
2
3
r=range(6, 10)
for i in r:
    print(i)
4
5
6
7
6
7
8
9

En pratique, on n’utilise pas la variable intermédiaire r ci-dessus et on écrit plutôt :

1
2
for i in range(6, 10):
    print(i)

Bien observer que le deuxième argument de la fonction range (dans l’exemple, c’est 10) est exclu des nombres générés. Toutefois, le nombre d’entiers générés par range(a,b) est \(\mathtt{b-a}\) (en supposant que \(\mathtt{a\leq b}\)).

Si \(\mathtt{n\geq 0}\) est un entier, l’expression range(n) est un raccourci syntaxique pour range(0,n) :

1
2
for i in range(3):
    print(i)
3
4
5
0
1
2

Affichage sur une même ligne et boucle for

Soit à réaliser avec une boucle for l’affichage suivant :

----------------
0 1 2 3 4 5 6 7 8 9
----------------

Pour éviter le saut de ligne après l’affichage de chaque entier et pour séparer chaque nombre du précédent d’une espace, on utilise l’argument nommé end = " " :

1
2
3
4
5
print("----------------")
for i in range(10):
    print(i, end = " ")
print()
print("----------------")
6
7
8
----------------
0 1 2 3 4 5 6 7 8 9
----------------
  • Ligne 7 : chaque entier est séparé du précédent par un espace. Aucun saut de ligne n’est effectué lors de l’exécution de la boucle.
  • Ligne 4 : permet d’effectuer un saut de ligne entre le dernier chiffre affiché (ligne 7) et la ligne formée de pointillés (ligne 8)

Omettre l’appel à print en sortie de boucle provoque un affichage incorrect :

1
2
3
4
5
print("----------------")
for i in range(10):
    print(i, end = " ")
print()
print("----------------")
6
7
8
----------------
0 1 2 3 4 5 6 7 8 9
----------------

Pour bien comprendre la rôle de end=" " dans print(i, end=" "), il suffit d’observer le résultat du code ci-dessous où le end=" " est remplacé par, par exemple, la chaîne end="xxx" :

1
2
3
4
5
print("----------------")
for i in range(10):
    print(i, end="xxx")
print()
print("----------------")
6
7
8
----------------
0xxx1xxx2xxx3xxx4xxx5xxx6xxx7xxx8xxx9xxx
----------------

Calcul d’une somme

On se donne un entier \(n\geq 0\), on lance un dé \(n\) fois et on fait la somme des numéros lus. Par exemple, pour \(n=5\), les coups de dés sont

6, 1, 1, 5, 6

dont la somme va être \(6 + 1 + 1 + 5 + 6 = 19\).

Pour effectuer ce genre de somme, il faut répéter \(n\) fois :

  • le tirage du dé,
  • l’ajout du numéro

voilà pourquoi on a besoin d’une boucle for. La somme à calculer est placée dans une variable s qui au départ vaut 0 et qui à chaque étape de la boucle for augmente du numéro tiré. Voici comment évolue s si \(n=5\) et si le tirage est 6, 1, 1, 5, 6 :

Tirage du dé Valeur de s
Néant 0
6 6
1 7
1 8
5 13
6 19

D’où le code ci-dessous :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
from random import randint

n=5
s=0

for i in range(n):
    de = randint(1,6)
    print(de)
    s = s + de

print("Valeur de s :", s)
12
13
14
15
16
17
6
1
1
5
6
Valeur de s : 19
  • Ligne 1 : on a besoin d’importer randint pour tirer le dé
  • Ligne 3 : le nombre de lancer de dé.
  • Ligne 4 : on initialise la somme à 0 (on a encore rien ajouté) et non pas à la première valeur du tirage, cela donne un code plus simple.
  • Ligne 7-8 : les deux actions à répéter : le tirage du dé, l’ajout du numéro. A chaque étape de la boucle, s contient la somme de toutes les valeurs tirés depuis le début de l’expérience.
  • Ligne 11 : une fois les n dés lancés, s contient la somme de tous les numéros.