La clause else attachée à une boucle for en Python reste l’une des constructions les plus mal comprises du langage. Elle n’a rien à voir avec le else conditionnel classique : elle s’exécute uniquement quand la boucle se termine sans rencontrer de break. Cette propriété en fait un outil redoutable pour la recherche dans les séquences.
Mécanisme interne du else sur une boucle for Python
Le bloc else d’une boucle for s’exécute après la dernière itération, à condition qu’aucune instruction break n’ait interrompu le parcours. Si la séquence est vide, le else s’exécute aussi, puisque le for ne rencontre jamais de break.
A lire en complément : Point d'exclamation à l'envers : comment faire ?
Nous recommandons de lire ce else comme « si aucun break n’a été déclenché ». Cette lecture lève toute ambiguïté. Le piège fréquent consiste à interpréter else comme « si la liste est vide » ou « si la condition du for est fausse », deux lectures incorrectes.
Différence avec un flag booléen
Sans la clause else, la recherche d’un élément dans une séquence impose généralement un drapeau found initialisé à False, basculé à True dans le corps de la boucle, puis testé après la boucle. Le else élimine cette variable intermédiaire et rend le flux de contrôle explicite.
Lire également : Astuces méconnues pour maîtriser le webmail Bbox
Le gain ne se mesure pas en performance brute (le bytecode reste comparable). Il se situe dans la lisibilité : le lecteur du code identifie immédiatement le schéma « recherche avec sortie anticipée ».

Recherche linéaire dans une liste avec for else
Le cas d’usage canonique, c’est la recherche d’un élément satisfaisant une condition dans une liste. Le break interrompt la boucle dès que l’élément est trouvé, et le else gère le cas d’absence.
Prenons un exemple concret. Nous cherchons le premier nombre négatif dans une séquence de données :
for element in donnees:
if element < 0:
print("Premier négatif :", element)
break
else:
print("Aucun élément négatif dans la séquence")
Le print du else ne s’exécute que si la boucle parcourt l’intégralité de la liste sans trouver de nombre négatif. Le break est la seule instruction qui empêche l’exécution du else.
Recherche avec range et index
Quand la position dans la séquence compte autant que la valeur, on combine range avec len pour obtenir l’index :
for i in range(len(sequence)):
if sequence[i] == cible:
print("Trouvé à l'index", i)
break
else:
print("Absent de la séquence")
Cette construction remplace avantageusement un try/except autour de list.index(), qui lève une ValueError en cas d’absence. Le for/else rend le flux explicite sans recourir à la gestion d’exceptions pour du contrôle de flux, une pratique que nous déconseillons dans ce contexte.
For else imbriqué : recherche dans des séquences multidimensionnelles
La vraie puissance de la construction apparaît avec des boucles imbriquées. Chercher un élément dans une liste de listes sans for/else génère du code difficilement lisible, avec des flags ou des fonctions auxiliaires.
for ligne in matrice:
for element in ligne:
if element == cible:
print("Trouvé :", element)
break
else:
continue
break
else:
print("Absent de la matrice")
Le pattern else/continue/break pour sortir de boucles imbriquées mérite une explication. Le else de la boucle interne déclenche continue sur la boucle externe, ce qui la fait avancer normalement. Si le break interne s’exécute (élément trouvé), le else interne est sauté, le continue n’est pas atteint, et le break externe met fin à la recherche.
C’est l’un des rares cas où ce double break via else reste plus lisible que l’alternative. Pour trois niveaux d’imbrication ou plus, extraire la recherche dans une fonction avec return devient préférable.

While else et for else : quand choisir l’un ou l’autre
La clause else fonctionne aussi avec while. La logique est identique : le else s’exécute si la boucle while se termine parce que sa condition devient False, pas à cause d’un break.
En pratique, nous observons que le for/else couvre la majorité des cas de recherche dans les séquences, pour une raison simple : la boucle for itère sur une collection finie. Le while/else s’impose quand la condition d’arrêt ne dépend pas d’un itérateur, par exemple lors d’une attente active avec un time-out logique.
- Utilisez for/else quand vous parcourez une séquence (list, tuple, range, générateur) à la recherche d’un élément satisfaisant une condition.
- Utilisez while/else quand la boucle dépend d’une condition externe (état réseau, file d’attente, convergence d’un algorithme) et que le break signale un résultat trouvé avant épuisement.
- Évitez d’utiliser else sur une boucle qui ne contient aucun break : le else s’exécutera systématiquement, ce qui rend la construction trompeuse et inutile.
Pièges courants et bonnes pratiques avec for else en Python
Un else sans break dans le corps de la boucle est un bug logique silencieux. Python ne lève aucune erreur, mais le bloc else devient du code mort qui s’exécute à chaque passage, donnant une fausse impression de sécurité.
Autre piège : placer des instructions entre le for et le else. Toute ligne de code entre la fin du bloc for et le mot-clé else provoque une SyntaxError. Le else doit être au même niveau d’indentation que le for, immédiatement après le bloc indenté.
- Toujours vérifier la présence d’au moins un break dans le corps de la boucle avant d’ajouter un else.
- Commenter le else avec une indication claire, par exemple
# pas de break déclenché, pour les relecteurs peu familiers avec la construction. - Préférer une fonction dédiée avec return quand la logique de recherche dépasse une dizaine de lignes ou implique plus de deux niveaux d’imbrication.
Le for/else de Python n’est pas une curiosité syntaxique. C’est le pattern natif du langage pour la recherche avec sortie anticipée. Mal compris, il produit du code confus. Bien maîtrisé, il élimine les variables temporaires et exprime directement l’intention de recherche dans la structure de contrôle elle-même.

