Skip to content

Et pour quelques elif de plus

26 janvier 2017

Face à une succession de if-elif-elif-elif-… longue comme un générique de film, il peut être tentant de les remplacer par un switch-case comme on peut en voir en C, PHP, Java, etc. C’est simplement impossible en Python car cette instruction n’existe pas.

Plusieurs propositions pour l’inclure dans le langage ont été faites mais elles ont été rejetées car Guido Van Rossum ne les a pas trouvées convaincantes. Son argumentaire détaillé est disponible dans la PEP 3103 publiée en 2006.

L’enchaînement de conditions que l’on souhaite éviter :

if personnage == "Le manchot":
    acteur = "Clint Eastwood"
elif personnage == "Colonel Douglas Mortimer":
    acteur = "Lee Van Cleef"
elif personnage == "El Indio":
    acteur = "Gian Maria Volontè"
#je vous fais grâce de toute la distribution
else:
    acteur = None

La FAQ de la documentation python explique comment se passer du switch (pour python 2, pour python 3). Inutile le lire les deux, c’est la même réponse à chaque fois. Elle recommande l’utilisation d’un dictionnaire. C’est aussi la solution la plus courante que l’on trouve dans du code Python.

L’équivalent du code précédent avec un dictionnaire est :

d = {"Le manchot": "Clint Eastwood", 
     "Colonel Douglas Mortimer": "Lee Van Cleef",
     "El Indio": "Gian Maria Volontè"}

acteur = d.get("El Indio", None)

Comme la structure switch n’est pas disponible dans le langage, plusieurs tentatives ont été faites pour l’ajouter à partir des structures existantes. Comme on peut s’y attendre, le code est plus verbeux et, à mon avis, la solution à base de dictionnaire reste préférable. Parmi les essais disponibles dans pypi.python.org, on peut trouver plusieurs choix d’interface :

Switchcase qui utilise l’instruction break de manière similaire au switch des autres langages : sans l’instruction break, les cas suivants sont automatiquement considérés comme vrai. Fonctionnalité permettant des comportments astucieuses mais qui est aussi un nid à bogues difficile à comprendre. C’est donc probablement une excellente idée de l’avoir ajoutée.

Switch qui a une interface me semblant plus simple à comprendre. La simulation du break est fait par un paramètre facultatif, ce qui s’écarte du switch canonique.

Pyswitch qui utilise les annotations pour définir les différents cas. Je ne suis pas sûr que ce soit le plus lisible mais c’est un choix original.

Une autre solution est de transformer le code en remplaçant les tests par du polymorphisme. Avec l’exemple précédent, on aurait :

class Personnage:
    acteur = None


class LeManchot(Personnage):
    acteur = "Clint Eastwood"


class ColonelDouglasMortimer(Personnage): 
    acteur = "Lee Van Cleef"


class ElIndio(Personnage):
    acteur = "Gian Maria Volontè"

p.acteur # p étant une instance d'une des classes précédente

Il n’est pas nécessaire que p soit une instance héritant de Personnage. Il suffit que l’interface soit identique. Cette transformation n’est pas spécifique à Python, elle est utilisable dans tous les langages objet.

Publicités

From → Python

Laisser un commentaire

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s

%d blogueurs aiment cette page :