2.13. Contrôle des boucles

Deux mots-clés modifient le déroulement d’une boucle :

  • break – quitte immédiatement la boucle.

  • continue – ignore le reste de l’itération en cours et passe à la suivante.

Les deux s’appliquent à la boucle la plus interne dans laquelle ils apparaissent.

2.13.1. break

Utilisez break pour arrêter une boucle dès qu’une condition est remplie. Le motif classique « rechercher et arrêter » :

found = None
for item in items:
    if matches(item):
        found = item
        break

if found is not None:
    print("found:", found)

Dans une boucle while True:, break est la façon de terminer la boucle :

while True:
    line = next_line()
    if line == "quit":
        break
    process(line)

2.13.2. continue

Utilisez continue pour ignorer le reste du corps et passer directement à l’itération suivante. Pratique pour filtrer des éléments à l’intérieur d’une boucle :

for n in numbers:
    if n < 0:
        continue            # skip negatives
    print(n)

Le même effet peut s’écrire à l’aide d’un bloc if entourant le reste du corps. continue est parfois plus clair lorsque la condition d’exclusion est plus facile à énoncer d’emblée que la condition de conservation.

À l’intérieur d’une boucle, continue joue le même rôle qu’un return anticipé dans une fonction : passer outre les cas que vous ne traitez pas et garder le travail principal à plat, au niveau d’indentation extérieur. La boucle filtrer-puis-traiter en est la forme canonique :

for item in items:
    if item is None:
        continue
    if not item.is_valid():
        continue
    process(item)

La ligne indentée process(item) représente le travail réel ; chaque garde au-dessus indique précisément quels éléments sont ignorés.

2.13.3. else sur une boucle

Les boucles for et while acceptent toutes deux un bloc else facultatif. Il s’exécute lorsque la boucle se termine sans rencontrer de break. L’usage le plus courant est une boucle de recherche qui souhaite un repli si rien n’a été trouvé :

for item in items:
    if matches(item):
        print("found:", item)
        break
else:
    print("no match")

Si un break se déclenche, le bloc else est ignoré. Lisez la construction comme « for X in Y: … ; sinon, si nous ne sommes jamais sortis, faire Z ».

2.13.4. Motifs de boucle courants

Quelques motifs reviennent souvent dans les scripts réels :

  • Interrogation (polling) – attendre qu’une condition devienne vraie avant de continuer. Le corps utilise pass, l’instruction « ne rien faire » de Python ; chaque bloc indenté doit contenir au moins une instruction, et pass est la façon de dire « ne rien faire ici » :

    while not ready():
        pass
    proceed()
    
  • Machine à états – une seule boucle while True: qui choisit quoi faire en fonction d’une variable d’état. Utile lorsque le travail se divise proprement en quelques phases nommées :

    state = "header"
    for line in lines:
        if state == "header":
            if line.startswith("---"):
                state = "body"
        elif state == "body":
            print(line)
    
  • Accumulation – construire un résultat tout en parcourant une séquence :

    total = 0
    for x in samples:
        total += x
    mean = total / len(samples)
    

    De nombreuses boucles d’accumulation ont un équivalent en une ligne à l’aide d’une fonction intégrée. Optez pour la fonction intégrée lorsqu’elle s’applique :

    • sum() – additionne tous les éléments d’un itérable.

    • max() / min() – le plus grand ou le plus petit élément.

    • any()True si au moins un élément est vrai.

    • all()True seulement lorsque tous les éléments sont vrais.

    • sorted() – une nouvelle liste contenant les éléments triés.

    • len() – le nombre d’éléments (lorsque l’itérable connaît sa longueur).

    >>> samples = [3, 1, 4, 1, 5, 9, 2, 6]
    >>> sum(samples)
    31
    >>> sum(samples) / len(samples)        # mean
    3.875
    >>> max(samples)
    9
    >>> min(samples)
    1
    >>> sorted(samples)
    [1, 1, 2, 3, 4, 5, 6, 9]
    >>> any([False, False, True])
    True
    >>> all([True, True, False])
    False
    

    La version intégrée est plus courte, plus claire et généralement plus rapide que d’écrire la même boucle à la main.