La clause else après une boucle for en Python provoque régulièrement de la confusion, y compris chez des développeurs expérimentés. Le mot-clé else, associé mentalement aux conditions if, change de sens quand il suit une boucle. Son exécution dépend directement de la présence ou non d’un break dans le corps de la boucle, et surtout de savoir si ce break a été déclenché.
Pourquoi else sur une boucle for Python ne signifie pas « sinon »
Le piège de lecture vient du mot lui-même. Dans un bloc if/else, else signifie « si la condition n’est pas remplie ». Appliqué à une boucle for, le réflexe est de lire « si la boucle ne s’exécute pas ». Ce n’est pas le comportement réel.
Lire également : Installing Python with pip derrière un proxy ou en entreprise : que faire ?
Le bloc else d’une boucle for s’exécute quand la boucle se termine normalement, c’est-à-dire quand toutes les itérations ont été parcourues sans rencontrer d’instruction break. Si un break interrompt la boucle avant la fin, le bloc else est ignoré.
La documentation Python classe cette construction dans les « instructions composées ». Le else n’est pas une extension du break : il fait partie intégrante du bloc de boucle. Certains développeurs trouvent qu’un mot comme nobreak ou alors aurait été plus explicite, mais la syntaxe est fixée depuis les premières versions du langage.
A lire aussi : Optimiser le stockage : de Mo en Go

Comportement du break dans for else : exécution pas à pas
Prenons un cas concret. Vous cherchez un élément dans une liste et voulez exécuter du code uniquement si l’élément n’a pas été trouvé :
for element in ma_liste:
if element == cible:
print(« Trouvé »)
break
else:
print(« Pas trouvé »)
Si la variable cible correspond à un élément de ma_liste, le break s’exécute, la boucle s’arrête et le bloc else est sauté. Le print(« Pas trouvé ») n’apparaît jamais.
Si aucun élément ne correspond, la boucle parcourt toute la liste sans jamais déclencher le break. À la sortie naturelle de la boucle, Python exécute le bloc else et affiche « Pas trouvé ».
Trois scénarios de sortie de boucle for
- La boucle se termine normalement (toutes les itérations parcourues) : le bloc else s’exécute.
- Un break interrompt la boucle : le bloc else est ignoré.
- Une exception ou un return interrompt la boucle : le bloc else est également ignoré, un point rarement mentionné dans les tutoriels classiques.
Ce troisième cas compte. Si votre boucle for se trouve dans une fonction et qu’un return intervient avant la fin des itérations, le else ne sera pas atteint. Même chose pour une exception non interceptée dans le corps de la boucle.
Boucles for imbriquées et clause else : le piège du break interne
L’instruction break ne quitte que la boucle la plus interne. Dans des boucles imbriquées, le comportement du else peut devenir contre-intuitif si on ne garde pas ce principe en tête.
for ligne in matrice:
for valeur in ligne:
if valeur == cible:
break
else:
continue
break
Ici, le break dans la boucle interne ne sort que de cette boucle interne. Le else de la boucle interne s’exécute si et seulement si cette boucle interne a parcouru tous ses éléments sans break. La boucle externe, elle, continue son cours. Le else de la boucle externe reste indépendant du break interne.
Ce pattern « break imbriqué avec else et continue » sert à propager une interruption vers la boucle parente. Il fonctionne, mais la lisibilité en souffre. Extraire la boucle interne dans une fonction séparée avec un return simplifie souvent le code.
Pylint et la règle useless-else-on-loop : quand else est superflu
L’outil d’analyse statique Pylint intègre la règle useless-else-on-loop (W0120). Elle se déclenche quand un bloc else est attaché à une boucle qui ne contient aucun break.
Sans break dans le corps de la boucle, le else s’exécutera systématiquement après la boucle. Son contenu pourrait être placé directement après la boucle, au même niveau d’indentation, sans changer le comportement du programme. Le else devient alors du bruit syntaxique.
- Si votre boucle for contient un break conditionnel, le else a un rôle logique : il distingue la fin naturelle de l’interruption.
- Si votre boucle for ne contient aucun break, le else est inutile et Pylint vous le signalera.
- Si votre boucle for contient un return au lieu d’un break, le else est techniquement actif mais souvent remplaçable par du code après la boucle.
Cette règle Pylint montre que for else n’a d’intérêt réel qu’en présence d’un break. Les outils de qualité de code encadrent désormais cet usage plutôt que de le laisser comme une curiosité syntaxique.

Cas d’usage légitime du for else en Python
Le pattern le plus courant reste la recherche dans un itérable. Vous parcourez une collection, vous cherchez un élément qui satisfait une condition, et vous voulez exécuter un traitement spécifique si l’élément n’est pas trouvé.
Sans for else, le code classique utilise une variable drapeau (un booléen initialisé à False, passé à True quand l’élément est trouvé, puis testé après la boucle). La clause else élimine ce drapeau et rend l’intention plus directe.
for utilisateur in base:
if utilisateur.email == recherche:
traiter(utilisateur)
break
else:
creer_utilisateur(recherche)
Le else remplace ici un flag booléen « trouvé » et le test conditionnel qui l’accompagnerait après la boucle. Le code passe de six ou sept lignes à quatre.
Limites de lisibilité
La syntaxe reste déroutante pour les lecteurs qui découvrent le code. Dans un projet collaboratif, un commentaire au-dessus du else (# aucun break déclenché) peut éviter des malentendus. Certaines équipes préfèrent interdire purement le for else dans leurs conventions de style au profit du pattern avec drapeau, jugé plus explicite malgré sa verbosité.
La clause else sur une boucle for Python reste un outil précis et légitime, à condition de l’utiliser exclusivement avec un break. Sans break, elle n’a pas de raison d’exister. Avec un break, elle remplace proprement les variables drapeaux dans les scénarios de recherche. Garder en tête que return et les exceptions court-circuitent aussi le else évite les bugs silencieux dans du code plus complexe.

