Vidéo 31 : while vs 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 31 : while vs for

Boucle for vs boucle while

Python dispose de deux types de boucle : la boucle for et la boucle while. Elles ont chacune des usages spécifiques.

Usage canonique de la boucle for

La boucle for s’emploie si :

  • une action doit être effectuée un nombre prédéterminé de fois, et, surtout, connu avant l’exécution de la boucle. Par exemple, s’il faut afficher 42 nombres vérifiant une certaine propriété, on utilise une boucle du type for i in range(42).
  • on parcourt une liste entre deux indices connus à l’avance, ce qui peut être la totalité de la liste ou, par exemple, de la 5ème position à l’avant-avant dernière.

Par exemple, étant donné une liste L de nombres, si on cherche à déterminer combien L contient d’entiers positifs, on utilisera une boucle d’en-tête du type for x in L ou encore for i in range(len(L)).

Usage canonique de la boucle while

La boucle while s’emploie si une action doit être répétée tant qu’une certaine condition reste vraie et sans qu’on sache à l’avance combien de fois la boucle va être répétée. Par exemple,

  • on a une liste d’entiers et on cherche le premier entier de la liste qui soit pair ;
  • on cherche la plus petite puissance de 10 qui dépasse un entier donné.

Usage inapproprié d’une boucle while

Le programme ci-dessous utilise une boucle while pour afficher les 5 premiers multiples de 10 :

1
2
3
4
5
6
i = 1
while i <= 5:
  print(10 * i)
  i = i + 1

print("Fin")
 7
 8
 9
10
11
12
10
20
30
40
50
Fin

Le code while_inapproprie.py est un usage non recommandé de la boucle while. En effet, le code contient des instructions inutiles par rapport à une boucle for :

  • Ligne 1 : initialisation inutile, c’est automatique avec une boucle for.
  • Ligne 2 : test de condition, automatique avec la boucle for.
  • Ligne 4 : incrémentation inutile, c’est automatique avec une boucle for.

Comparer avec un code équivalent écrit avec une boucle for :

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

print("Fin")

Boucle while et parcours de liste

Usuellement, le parcours d’une liste est associé à une boucle for. Toutefois, dans certaines circonstances, il est plus approprié de parcourir une liste avec une boucle while.

Soit à définir un code Python qui, partant d’une liste L d’entiers détermine si L ne contient que des entiers positifs. Plus précisément, le code doit définir un booléen nommé tousPositifs qui vaut True si L ne contient que des entiers positifs et False sinon.

L’idée est de parcourir la liste L avec une boucle while à l’aide d’un indice i valide et tant que le terme courant L[i] est positif ou nul :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
L= [31, 82, -42, 32, -81]

i=0
n = len(L)

while i<n and L[i]>=0:
    i = i + 1

tousPositifs = (i==n)

print(L, tousPositifs)
12
[31, 82, -42, 32, -81] False
  • Ligne 6 : la condition doit D’ABORD gérer la sortie de liste d’où la condition i < n qui évite le débordement d’indice.

  • Ligne 6 : la condition doit aussi filtrer suivant le critère, ici le fait que chaque terme soit positif.

  • Ligne 9 : Il s’agit de définir le booléen.

    • Si un élément négatif est apparu dans la liste, soit i son indice. Alors comme le booléen i<n and L[i]>=0 vaut False (puisque L[i]<0), la boucle while s’arrête et l’indice i vérifie i<n.
    • En revanche, si aucun élément de la liste n’est strictement négatif, le corps de la boucle while sera exécuté tant que la condition i<n sera vraie. Lorsque i = n-1, le corps de la boucle est exécuté et i devient i+1 donc i=n et la boucle se termine.

    Donc, ce qui différencie les deux cas, c’est la valeur de i en sortie de boucle : dans le second cas, i vaut n et pas dans le premier cas, ce qui explique la définition ligne 9 de tousPositifs.

Même si c’est un détail, noter que le code suivant devrait être évité :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
L= [31, 82, -42, 32, -81]

i=0

while i< len(L) and L[i]>=0:
    i = i + 1

tousPositifs = (i==len(L))

print(L, tousPositifs)
  • Ligne 5 : à chaque tour de boucle, l’appel len(L) est recalculé alors que len(L) est un nombre qui ne varie pas.