IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

switch/case & default


Sujet :

Python

  1. #1
    Invité(e)
    Invité(e)
    Par défaut switch/case & default
    Bonjour,

    Actuellement j'utilise un dictionnaire pour avoir une sorte de switch/case en python :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    def dispatch(self, key):
        # Dictionary of functions                           
        functs = {                                                        
            'key_1'        : self.func_1,
            'key_2'        : self.func_2,
            'key_3'        : self.func_3,
        }
     
        functs[key]
    Ainsi, quand j'appelle ma fonction dispatch avec une clé 'key', je vais appeller la fonction qui va bien (func_1, func_2 ou func_3).

    Mon problème ici, c'est que je n'ai pas de cas par défaut. J'ai cherché un peu, mais j'ai rien trouvé de probant pour cela.

    Savez-vous comment je peux rajouter un cas par défaut qui me dit :
    - Si ma clé 'key' n'est pas dans le dictionnaire functs, alors j'appelle la fonction 'funct_default' ?

    Merci

  2. #2
    Membre éprouvé

    Profil pro
    Inscrit en
    Août 2004
    Messages
    723
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 723
    Points : 923
    Points
    923
    Par défaut
    Tu peux te servir de la méthode .get de ton dictionnaire, qui permet d'avoir une valeur par défaut si la clé n'existe pas :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    def dispatch(self, key):
        # Dictionary of functions                           
        functs = {                                                        
            'key_1'        : self.func_1,
            'key_2'        : self.func_2,
            'key_3'        : self.func_3,
        }
     
        functs.get(key, self.func_default)

  3. #3
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 462
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 462
    Points : 9 249
    Points
    9 249
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Voilà une solution un peu simpliste, mais qui fonctionne:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
     
    def func_1():
        print "func_1"
     
    def func_2():
        print "func_2"
     
    def func_3():
        print "func_3"
     
    def dispatch(key):
     
        functs = {                                                        
            'key_1'        : func_1,
            'key_2'        : func_2,
            'key_3'        : func_3
        }
        if key in functs:
            functs[key]()
        else:
            print u"pas trouvé la fonction demandée!"
     
     
    dispatch('key_1')
    func_1
     
    dispatch('key_2')
    func_2
     
    dispatch('key_3')
    func_3
     
    dispatch("nimportequoi")
    pas trouvé la fonction demandée!
    Tyrtamos
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

  4. #4
    Membre éprouvé
    Avatar de Antoine_935
    Profil pro
    Développeur web/mobile
    Inscrit en
    Juillet 2006
    Messages
    883
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur web/mobile

    Informations forums :
    Inscription : Juillet 2006
    Messages : 883
    Points : 1 066
    Points
    1 066
    Par défaut
    Voici une troisième version, en passant
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    try:
        functs[key]()
    except KeyError:
        defaultFunction()
    Comme ça vous aurez de quoi réagir à tous les besoin

  5. #5
    Membre éclairé
    Profil pro
    Ingénieur sécurité
    Inscrit en
    Février 2007
    Messages
    574
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur sécurité
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2007
    Messages : 574
    Points : 751
    Points
    751
    Par défaut
    Citation Envoyé par Antoine_935 Voir le message
    Voici une troisième version, en passant
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    try:
        functs[key]()
    except KeyError:
        defaultFunction()
    Comme ça vous aurez de quoi réagir à tous les besoin
    Je suis pas fan de cette version, à cause du contrôle du flow par les exceptions. Je trouve pas que ce soit une très bonne pratique, sauf cas particulier. Je trouve la méthode 1 meilleure.
    C'est juste histoire de pinailler...

  6. #6
    Membre chevronné

    Profil pro
    Account Manager
    Inscrit en
    Décembre 2006
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Account Manager

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 301
    Points : 1 752
    Points
    1 752
    Par défaut
    Citation Envoyé par dahtah Voir le message
    Je suis pas fan de cette version, à cause du contrôle du flow par les exceptions. Je trouve pas que ce soit une très bonne pratique, sauf cas particulier. Je trouve la méthode 1 meilleure.
    C'est juste histoire de pinailler...
    Je pense aussi que le try... except... soit à réserver pour les cas exceptionniels comme dans le code suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    try:
        """Application d'une méthode sans try si cela existe."""
    except:
        """Application d'un try car on n'a pas mieux."""

  7. #7
    Membre habitué
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    141
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mai 2008
    Messages : 141
    Points : 184
    Points
    184
    Par défaut
    Citation Envoyé par dahtah Voir le message
    Je suis pas fan de cette version, à cause du contrôle du flow par les exceptions.
    Et pourtant, c'est un "pattern" très courant en Python : le fameux EAFP (Easier to Ask Forgiveness than Permission = Il est plus facile de demander pardon que la permission).

    Ce pattern est à utiliser dans les cas où tu sais que les erreurs seront marginales par rapport aux cas corrects car, dans ces cas-là, on ne perd pas de temps à vérifier la présence de la clé.
    Ca permet aussi de ne pas restreindre son code (par exemple, il vaut mieux faire ce pattern plutôt que de faire appel à isinstance).
    Toutefois, dans ton cas, avec l'utilisation d'un dictionnaire, rien ne vaut l'appel à la méthode get.

    Allez, ma version à moi, qui est inspiré d'un (vieux ?) post de Guido sur le dispatching :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    class Dispatcher(object):
        def key_1(self):
            print 'function 1'
        def key_2(self):
            print 'function 2'
        def key_3(self):
            print 'function 3'
        def default(self):
            print 'unknown function!'
        def dispatch(self, key):
            try:
                # ou alors "getattr(self, key)()", je ne sais plus lequel est le mieux.
                self.__getattribute__(key)()
            except AttributeError:
                self.default()
    L'avantage ? Tu peux définir une nouvelle fonction ou en supprimer une sans avoir à maintenir à jour un dictionnaire.

  8. #8
    Membre éprouvé
    Avatar de Antoine_935
    Profil pro
    Développeur web/mobile
    Inscrit en
    Juillet 2006
    Messages
    883
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur web/mobile

    Informations forums :
    Inscription : Juillet 2006
    Messages : 883
    Points : 1 066
    Points
    1 066
    Par défaut
    Citation Envoyé par dahtah Voir le message
    C'est juste histoire de pinailler...
    Ah, bah ça me permet de pinailler aussi Si j'utilise cette version, c'est parce que c'est la plus performante des trois (enfin, par rapport au get, c'est à vérifier, mais c'est possible). Et comme le functs[key]() est la seule instruction dans le try, je suis sur de contrôler ce que je fais.

    La version de nardo est pas mal aussi. Un bel exemple concret est le BaseHTTPHandler.

  9. #9
    Membre éclairé
    Profil pro
    Ingénieur sécurité
    Inscrit en
    Février 2007
    Messages
    574
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur sécurité
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2007
    Messages : 574
    Points : 751
    Points
    751
    Par défaut
    Citation Envoyé par nardo47 Voir le message
    Ce pattern est à utiliser dans les cas où tu sais que les erreurs seront marginales par rapport aux cas corrects
    Ce qui n'est pas le cas ici...

    Citation Envoyé par nardo47 Voir le message
    Ca permet aussi de ne pas restreindre son code (par exemple, il vaut mieux faire ce pattern plutôt que de faire appel à isinstance).
    Tout à fait d'accord

    Si j'utilise cette version, c'est parce que c'est la plus performante des trois (enfin, par rapport au get, c'est à vérifier, mais c'est possible)
    Je pense pas qu'attraper + traiter une exception soit plus rapide que la méthode get. A vérifier.

    La version de nardo est pas mal aussi.
    Oui, même si je suis surpris de cette implémentation, pour la même raison que précédement (un test me semble plus approprié q'un except dans ce cas là). Mon jugement est peut être à revoir...

  10. #10
    Membre habitué
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    141
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mai 2008
    Messages : 141
    Points : 184
    Points
    184
    Par défaut
    Citation Envoyé par dahtah Voir le message
    Je pense pas qu'attraper + traiter une exception soit plus rapide que la méthode get.
    Ah nononon, c'est pas + rapide du tout.
    Le traitement de l'exception (EDIT : pas le traitement, mais le processus qui génère l'exception... le except quoi !) est assez long, il faut vraiment que les cas d'erreurs soient rares pour que le try/except vaille le coup au niveau des perfs.

    Citation Envoyé par dahtah Voir le message
    je suis surpris de cette implémentation
    J'avoue que, moi aussi, ça m'a surpris la première fois que j'ai vu un truc du genre.
    Mais on s'y fait, à la longue. (En tout cas, j'adore, moi !)

    Mince ! Du coup, j'ai confondu dahtah avec le PO !

    @DoObS : je te conseille fortement d'utiliser la méthode get de ton dictionnaire, comme te le conseillait oiffrig. C'est de + une méthode que tu risques d'utiliser fréquemment.

  11. #11
    Invité(e)
    Invité(e)
    Par défaut
    Wow !

    merci pour vos réponses !

    J'ai testé avec try/except, ça fonctionne, mais je vais également tester avec get(), qui amha semble plus sympa.

    merci !

Discussions similaires

  1. Passer d'un case à un default (Switch)
    Par Allspark dans le forum C#
    Réponses: 9
    Dernier message: 27/08/2010, 16h03
  2. switch case ET DEFAULT
    Par hellalaboy dans le forum Général VBA
    Réponses: 3
    Dernier message: 02/09/2009, 16h21
  3. [Tableaux] Problème avec Switch case
    Par philippef dans le forum Langage
    Réponses: 4
    Dernier message: 07/09/2005, 16h37
  4. probleme gestion condition switch - case
    Par DarkMax dans le forum Langage
    Réponses: 5
    Dernier message: 07/09/2005, 14h25
  5. [Language] aide sur les switch case
    Par pouss dans le forum Langage
    Réponses: 3
    Dernier message: 05/04/2005, 11h34

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo