En savoir plus

Les boucles

Au-delà de la séance : la boucle infinie que l'on veut exprès, et pourquoi les scientifiques fuient les boucles en calcul lourd.

La boucle infinie... voulue exprès#

En séance, la boucle infinie était un accident : on oubliait de faire avancer le compteur, la condition restait vraie pour toujours, le programme se figeait. Mais il arrive qu'on veuille une boucle qui ne s'arrête jamais toute seule. On l'écrit alors exprès, et on en sort avec break.

while True: touche = lireManette() if touche == "quitter": break # la seule porte de sortie bougerPersonnages() redessinerEcran()

C'est le cœur de presque tous les jeux vidéo : la « boucle de jeu » (game loop) tourne sans fin, souvent 60 fois par seconde. À chaque tour elle lit les commandes, met à jour le monde, puis redessine l'image. Un serveur web, un thermostat, un GPS font pareil : ils tournent « pour toujours » en attendant le prochain événement. Ici, la boucle infinie n'est pas un bug : c'est le moteur.

Une vraie boucle de jeu, ici, dans ton navigateur

Ton navigateur possède sa propre boucle de jeu (60 images par seconde). On la démarre, elle tourne sans fin... jusqu'à ce qu'une condition la fasse sortir (ici : ton clic, ou 300 images atteintes).

Tours de boucle (images)
0
État
à l'arrêt
while True Tant que personne ne déclenche le break, la boucle continue. C'est ça, un programme « vivant ».

Pourquoi les scientifiques fuient les boucles#

Une boucle Python qui parcourt un million de nombres, c'est un million de petits allers-retours dans l'interpréteur : à chaque tour, Python vérifie les types, range la variable, recommence. Lent. La parade des sciences des données s'appelle la vectorisation : on confie toute l'opération, d'un coup, à une bibliothèque écrite en C comme NumPy, qui balaie le tableau à pleine vitesse sans repasser par l'interpréteur à chaque élément.

La boucle : case par case

Une cellule traitée à la fois : la marque rouge se promène de l'une à l'autre.

La vectorisation : rangée entière

Toute une rangée d'un coup : le flash rose-rouge balaie le tableau d'un trait.

import numpy as np mesures = np.random.random(1_000_000) # Façon « boucle » : un tour d'interpréteur par élément (lent) total = 0.0 for valeur in mesures: total = total + valeur # Façon « vectorisée » : une seule instruction, exécutée en C (rapide) total = np.sum(mesures)

Les deux donnent le même résultat. Mais sur un million d'éléments, np.sum est typiquement 50 à 100 fois plus rapide que la boucle écrite à la main. Sur des données scientifiques réelles (millions de mesures, images, signaux), c'est la différence entre « instantané » et « va te chercher un café ».

Somme de 1 000 000 d'élémentsTemps typiqueVitesse relative
Boucle for en Python pur~ 60 a 120 ms1x (référence)
sum(liste) intégré de Python~ 8 a 15 ms~ 8x
np.sum(tableau) (NumPy, vectorisé)~ 1 ms~ 50 a 100x

Ordres de grandeur indicatifs (ils varient selon la machine). L'idée à retenir n'est pas le chiffre exact, mais le saut : laisser le code natif balayer les données bat presque toujours une boucle élément par élément.

Démo chrono : la façon d'écrire change tout

On ne peut pas faire tourner Python ici, mais le même principe vaut en JavaScript. Même calcul (somme des carrés), deux écritures : une qui crée des objets et rappelle une fonction à chaque élément (façon « boucle interprétée »), une compacte qui balaie directement le tableau (façon « vectorisée »). Lance le chrono sur ta machine.

Façon « boucle » (surcoût par élément)
-
Façon compacte (un seul balayage)
-

Le ternaire : une condition sur une seule ligne#

Dans une boucle, on veut souvent choisir une valeur différente à chaque tour selon une condition. Écrire un if / else complet de quatre lignes juste pour ça, c'est lourd. Python offre une condition qui tient sur une ligne et qui renvoie une valeur : l'expression conditionnelle, qu'on surnomme le « ternaire ».

mention = "réussi" if note >= 60 else "échec"

Ça se lit comme une phrase : « réussi, si la note est ≥ 60, sinon échec ». Même résultat que le bloc complet, dans une fraction de la place :

if / else classique (4 lignes)Ternaire (1 ligne)
if note >= 60:
    mention = "réussi"
else:
    mention = "échec"
mention = "réussi" if note >= 60 else "échec"

Son intérêt éclate dans une boucle, où il décide une valeur à chaque tour sans alourdir le code :

for note in [45, 72, 88, 30]: mention = "réussi" if note >= 60 else "échec" print(note, "->", mention)

Essaie : change la note, la mention se choisit en une ligne

Mention (choisie par le ternaire)
-
La ligne Python évaluée
-

Pourquoi « ternaire » ? C'est le seul outil de Python à trois opérandes : la condition, la valeur si vrai, la valeur si faux. La plupart des opérateurs sont binaires (+, == : deux opérandes). En C, en Java et en JavaScript, le même outil s'écrit avec des symboles : condition ? siVrai : siFaux. Python a préféré des mots dans un ordre qui se lit tout seul - mais attention, la valeur vient avant la condition, ce qui surprend au début.

À doser : le ternaire brille pour un choix simple entre deux valeurs. Pour de la logique à plusieurs branches, on garde un if / elif / else bien lisible.

Le réflexe à garder#

Deux idées à emporter de cette page :

SituationLe bon réflexe
Un programme « vivant » qui attend des événements (jeu, serveur)Une boucle infinie assumée : while True + break
Un gros calcul sur beaucoup de nombresÉviter la boucle Python : vectoriser avec NumPy

Le reste (parcourir une liste avec enumerate, mesurer le coût d'une boucle dans une boucle) viendra avec la séance sur les structures de données.