Aller au contenu

Les boucles

Objectifs de la section

2-4 Traitements conditionnels et répétés

Temps requis

60 minutes

Le traitement d'ensembles de données demande souvent d'appliquer un traitement spécifique à chaque entrée de ce jeu de données. Plutôt que de répliquer (copier-coller odieusement) le traitement dans le code, on forme un bloc d'instructions que l'on exécute plusieurs fois, chaque fois sur une entrée différente. Un autre usage fréquent des traitements répétitifs est pour la réalisation de méthodes de calcul numérique; plusieurs méthodes sont itératives : à chaque étape, on converge souvent légèrement plus vers la solution. Finalement, simplement pour interagir avec la personne utilisatrice, on utilise aussi souvent des traitements répétés : recommencer un traitement tant qu'il y a une erreur par exemple.

On appelle boucle les instructions qui permettent de répéter un traitement plusieurs fois. On trouve deux types de boucles :

  1. La boucle tant que (while): s'exécute tant qu'une condition est évaluée à vraie. On ne connait pas nécessairement le nombre d'itérations de la boucle;
  2. La boucle pour (for) : s'exécute pour un nombre déterminé d'itérations.

Dans les deux cas, il est important dans l'écriture du programme de s'assurer que les boucles s'arrêtent à un moment donné (que la condition d'arrêt est atteinte), autrement le programme exécutera toujours le même bloc d'instruction et sera pris à cet endroit.

La boucle while

Sections 5.0 à 5.2

La syntaxe de la boucle while est la suivante :

Structure de la boucle while
1
2
3
4
5
while condition_logique : 
    # Instructions dans la boucle
    # Instructions dans la boucle

# Instructions après la boucle

Indentation dans les boucles

Comme pour les instructions conditionnelles, l'indentation devant les instructions après la déclaration de la boucle indique quelles instructions doivent être répétées.

Par exemple, on souhaite qu'une personne saisisse un nombre positif à la console. On lui demande donc un nombre tant que celui-ci ne satisfait pas la contrainte.

Schéma d'exécution - Saisir un nombre positif

Saisir un nombre positif
1
2
3
4
5
6
7
8
print("Veuillez saisir un nombre positif.")
nombre = int(input())

while nombre <= 0:
    print("C'est pas bien compliqué, entrez n'importe quel nombre plus grand que 0 !")
    nombre = int(input())

print("Hourra ! Tu as saisi " + str(nombre) + " .")

Inversion de la condition

Plusieurs auraient une tendance naturelle à utiliser nombre > 0 comme condition dans le while, mais on veut écrire le code de façon à ce que la vérification de la condition (test logique retourne vrai), entraîne l'exécution du code, d'où pourquoi on « inverse » la façon de penser le problème. C'est ce que l'on appelle une clause de garde : sa vérification empêche le programme de poursuivre tant que les données ne sont pas valides. Elle est la gardienne de l'intégrité du programme.

La boucle while peut aussi être utilisée pour compter jusqu'à une certaine valeur, par exemple afficher les carrés des nombres entre 1 et 10. La boucle forconviendra souvent, mais systématiquement, à ces cas de figure.

Affichage des carrés
1
2
3
4
nombre = 1
while nombre <= 10:
    print(f"{nombre**2}")
    nombre += 1

Instruction +=

L'instruction += est simplement une forme abrégée de x = x + .... Des instructions similaires existent pour les autres opérations arithématiques.

La boucle for

Sections 6.0 à 6.2

La syntaxe de la boucle for est un peu plus complexe, car il faut définir un compteur pour déterminer le nombre d'itérations à faire. Cette boucle se compose de 2 morceaux (au lieu d'une unique condition dans le cas de la boucle while).

  • Un compteur de la boucle
  • Une séquence à parcourir, souvent générée par la fonction range
Structure de la boucle for
1
2
3
4
5
for compteur in range(init, limite, pas) : 
    # Instructions dans la boucle
    # Instructions dans la boucle

# Instructions après la boucle

Voici la spécification de la fonction range qui génère une séquence de nombres sur laquelle exécuter la boucle.

Paramètre Type Description
init Entier La valeur initiale de la séquence (inclue)
limite Entier La valeur maximale de la séquence (exclue)
pas Entier L'intervalle entre chaque élément de la séquence
Retour Séquence Une représentation de la séquence à parcourir.

La variable compteur (qu'on appelle souvent simplement i) déclarée dans la boucle contient la valeur courante du compteur. Voici quelques exemples de boucles for :

Les entiers de 1 à 10
1
2
3
4
for i in range(1, 11, 1):
    print(i)

## Pour afficher 10, il faut arrêter à 11, car l'instruction print s'exécute seulement pour les valeurs strictement plus petites que 11
Les entiers impairs de 5 à 17
for i in range(5, 18, 2):
    print(i)
Les entiers entre -5 et 5 en ordre décroissant
for i in range(5, -6, -1):
    print(i)

Raccourcis d'écriture de la fonction range

La fonction py range définie certains de ses paramètres par défaut, ce qui signifie que si l'on omet des paramètres, alors Python lui assigne automatiquement une valeur.

Par défaut, le pas vaut 1. Les deux appels ci-dessous sont équivalents.

Valeur du pas par défaut
for i in range(0, 10, 1):
    # Instructions dans la boucle

for i in range(0, 10):
    # Instructions dans la boucle

Par défaut, le pas vaut 1 et l'initialisation du compteur se fait à 0. Les deux appels ci-dessous sont équivalents.

Valeur du pas par défaut
for i in range(0, 10, 1):
    # Instructions dans la boucle

for i in range(10):
    # Instructions dans la boucle

On peut reprendre l'affiche des carrés des nombres de 1 à 10 avec une boucle for pour comparer les deux syntaxes. Ici la syntaxe avec une boucle for est plus courte, mais ce n'est pas toujours le cas.

Affichage des carrés
for nombre in range(1, 11):
    print(f"{nombre**2}")
Affichage des carrés
1
2
3
4
nombre = 1
while nombre <= 10:
    print(f"{nombre**2}")
    nombre += 1

La fonction arange

Section 6.3

La fonction arange définit dans numpy permet de générée une séquence, mais avec des nombres à virgule au lieu d'être limité à des entiers. La spécification de la fonction est la suivante.

Paramètre Type Description
init Nombre à virgule La valeur initiale de la séquence (inclue)
limite Nombre à virgule La valeur maximale de la séquence (exclue)
pas Nombre à virgule L'intervalle entre chaque élément de la séquence
Retour Séquence Une représentation de la séquence à parcourir.

Voici quelques exemples de la fonction arange.

Les nombres entre 1 et 3 avec un pas de 0.25
1
2
3
4
5
6
from numpy import arange

for i in arange(1.0, 3.1, 0.25):
    print(i) 

# Affiche 1.0, 1.25, 1.5, 1.75, 2.0, 2.25, 2.5, 2.75, 3.0
Pour afficher 3, il faut arrêter après 3 et avant 3.25 en raison de l'exclusion de la borne supérieure.

les nombres entre 1 et 2 avec un pas de 0.2
1
2
3
4
5
6
from numpy import arange

for i in arange(1.0, 2.1, 0.2):
    print(i)

# Affiche 1.0, 1.2, 1.4, 1.5999999999999999, 1.7999999999999998, 1.9999999999999998
Cet exemple démontre les problèmes d'arrondis qui peuvent survenir avec la fonction arange

La fonction linspace

Section 6.4

La fonction linspace permet d'obtenir aussi une séquence de nombres à virgule, mais utilise une approche différente de la fonction arange, ce qui réduit les erreurs d'arrondit. Plutôt que de définir un pas, la fonction linspace prend en compte le nombre total d'éléments dans la séquence générée. La division se fait de façon linéaire (d'où le nom « espace linéaire »). De plus, la borne supérieure est toujours l'un des éléments de la séquence.

Paramètre Type Description
init Nombre à virgule La valeur initiale de la séquence (inclue)
limite Nombre à virgule La valeur maximale de la séquence (inclue)
Nombre d'éléments Entier Le nombre d'éléments dans la séquence
Retour Séquence Une représentation de la séquence à parcourir.

Voici quelques exemples de la fonction linspace.

Les nombres entre 1 et 3 avec 5 éléments dans la séquence
1
2
3
4
5
6
from numpy import linspace

for i in linspace(1.0, 3.0, 5):
    print(i) 

# Affiche 1.0, 1.5, 2.0, 2.5, 3.0
Pour afficher 3, il faut arrêter après 3 et avant 3.25 en raison de l'exclusion de la borne supérieure.

les nombres entre 1 et 2 avec 6 éléments dans la séquence
1
2
3
4
5
6
from numpy import arange

for i in arange(1.0, 2.0, 6):
    print(i)

# Affiche 1.0, 1.2, 1.4, 1.6, 1.8, 2.0
Bien que des erreurs d'arrondis peuvent arriver avec la fonction linspace elle y est moins sujette que arange.

Pourquoi il y a plus d'erreurs d'arrondis avec arange qu'avec linspace ?

Pour répondre à cette question, écrivons un comportement équivalent aux deux fonctions avec une boucle while.

Boucle équivalente à arange
1
2
3
4
5
6
7
# Afficher les nombres entre 1 et 2 avec un pas de 0.2
valeur_initiale = 1.0
valeur_finale = 2.1
pas = 0.2
while valeur < valeur_finale:
    print(valeur)
    valeur += pas   # Accumulation d'erreurs d'arrondis
Boucle équivalente à linspace
# Afficher les nombres entre 1 et 2 avec 6 éléments dans la séquence
valeur_initiale = 1.0
valeur_finale = 2.0
nombre_elements = 6
element = 0
pas = (valeur_finale - valeur_initiale) / (nombre_elements - 1)

while element < nombre_elements:
    valeur = valeur_initiale + pas * element    # En repartant toujours de pas, on limite les erreurs au lieu de les accumuler
    print(valeur)
    element += 1  

On voit que le traitement différent explique la présence moins fréquente des erreurs d'arrondis. Toutefois, la fonction linspace est généralement un peu plus lente que la fonction arange pour cette raison.

Exercices

Boucle while

Page 94 et suivantes

Recommandés : 5.2, 5.3, 5.4, 5.5, 5.6, 5.7, 5.8, 5.10 et 5.24 Supplémentaires : 5.9, 5.12 et 5.23

Boucle for

Page 94 et suivantes

Recommandés : 6.1, 6.2, 6.4, 6.7 (attention à ne pas prendre de trop grandes valeurs !), 6.8 et 6.11 Supplémentaires : 6.9, 6.10