Définition
Dès qu'un programme pose une question, il doit savoir quoi faire des deux réponses. Un paiement passe ou ne passe pas, et le cas refusé mérite un traitement autant que l'autre. On pourrait écrire un second if portant la condition inverse, mais ces deux tests finissent toujours par se désynchroniser : quelqu'un modifie le premier, oublie le second, et il reste un trou ou deux branches qui s'exécutent à la suite.
else supprime ce risque. Il introduit le bloc qui s'exécute quand la structure à laquelle il se rattache n'a pas pris son chemin principal. Attaché à un if, il couvre tous les cas que les conditions précédentes ont laissés passer, sans que vous ayez à les nommer.
if solde >= montant:
valider_paiement()
else:
refuser_paiement()Remarquez qu'aucune condition ne suit le mot else, et que rien ne manque pour autant : ce qui n'a pas été attrapé au-dessus arrive ici par construction. C'est pourquoi un else ne peut jamais ouvrir une structure, seulement la refermer.
Une seule branche part, jamais les deux. Cette garantie vaut plus qu'elle n'en a l'air : après la structure, vous pouvez affirmer que la variable a reçu une valeur, quel que soit le chemin emprunté. Deux if indépendants ne promettent rien de tel.
Le else des boucles, la surprise de Python
Voici un ennui que tout le monde a rencontré. Vous parcourez une liste à la recherche d'un élément et vous sortez avec break dès que vous le trouvez. Une fois la boucle terminée, comment savoir si vous en êtes sorti parce que la recherche a abouti, ou parce que la liste était épuisée ? Le réflexe habituel consiste à poser un drapeau booléen avant la boucle et à le relire après.
Python offre plus court. for et while acceptent eux aussi un else, et beaucoup de développeurs expérimentés l'ignorent encore. Ce bloc s'exécute lorsque la boucle est allée jusqu'à son terme sans jamais rencontrer de break.
for utilisateur in utilisateurs:
if utilisateur.email == recherche:
print("Trouvé")
break
else:
# Atteint uniquement si aucun break n'a eu lieu
print("Aucun utilisateur avec cet e-mail")Le nom est mal choisi, personne ne le conteste, et « nobreak » aurait décrit la chose plus fidèlement. Lisez-le ainsi : la boucle a fini son parcours sans sortir en avance. Les lignes de drapeau disparaissent, et l'intention devient visible à l'endroit exact où elle se joue.
Un détail décide de tout : seul break annule ce bloc. Un continue saute à l'itération suivante sans rien annuler, et le else s'exécutera quand même à la fin. Un return, lui, quitte la fonction entière, donc rien de ce qui suit la boucle ne sera atteint. Le while obéit à la même règle : son else part quand la condition devient fausse, et saute quand un break l'interrompt.
Le else du try
Le troisième usage répond à un piège très concret. Quand un try enferme cinq lignes, le except placé en dessous surveille les cinq, y compris celles qui n'avaient aucune raison d'échouer de cette manière. Une erreur venue du traitement se fait alors passer pour une erreur d'ouverture, et vous cherchez longtemps au mauvais endroit.
Le bloc else d'un try ne s'exécute que si aucune exception n'a été levée. Il vient après le dernier except, et avant le finally s'il y en a un.
try:
fichier = open("donnees.csv") # La seule ligne réellement surveillée
except FileNotFoundError:
print("Fichier absent")
else:
traiter(fichier) # Ne tourne que si l'ouverture a réussi
finally:
print("Terminé") # Tourne dans tous les casTout ce qui n'a pas besoin d'être surveillé descend donc dans le else, et le try se réduit à l'opération risquée. Vous y gagnez un diagnostic honnête : le jour où ce except se déclenche, vous savez que le fichier est bien en cause.
Une exception levée à l'intérieur du else n'est pas rattrapée par le except écrit juste au-dessus : elle remonte comme si le try n'existait pas. Le comportement est voulu, mais il surprend la première fois qu'on le rencontre en production.
Quand s'en passer
Un else n'est pas toujours la bonne réponse. Le cas le plus fréquent est celui d'une fonction qui commence par écarter les entrées invalides avant de faire son vrai travail.
# Avec else : le vrai travail est décalé d'un cran
def facturer(client):
if client.est_actif:
return calculer(client)
else:
return 0
# Sans else : on écarte le cas fautif, on quitte, et la suite respire
def facturer(client):
if not client.est_actif:
return 0
return calculer(client)La seconde forme garde le cas nominal au niveau d'indentation le plus faible, là où l'œil le cherche en premier. Le return referme la branche fautive aussi sûrement qu'un else, sans rien imbriquer derrière lui.
Sur une fonction qui écarte quatre entrées douteuses avant de travailler, l'écart devient considérable : d'un côté un corps enfoui sous quatre niveaux d'imbrication, de l'autre quatre gardes alignées à gauche puis le traitement. Le même code ne se lit pas du tout de la même façon.
Questions fréquentes
Un else est-il obligatoire après un if ?
Non, un if seul est parfaitement valide et très courant : quand il n'y a rien à faire dans le cas contraire, n'écrivez rien. Le else devient nécessaire dès qu'une variable doit recevoir une valeur dans tous les cas, faute de quoi elle reste indéfinie sur les chemins non couverts et la ligne suivante lèvera une erreur.
Pourquoi le else d'une boucle ne s'exécute-t-il pas ?
Parce qu'un break a été rencontré quelque part dans la boucle, et c'est la seule chose qui annule ce bloc. Un break caché dans une condition rarement remplie suffit à créer la surprise. Une boucle qui tourne sur une séquence vide, elle, exécute bien son else : zéro itération, donc aucun break.
Quelle différence entre else et elif ?
elif pose un nouveau test, else n'en pose aucun. Une chaîne peut compter autant de elif que nécessaire mais un seul else, obligatoirement en dernière position puisqu'il ramasse tout ce qui reste. Une branche écrite après lui ne serait jamais atteinte.