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 :

Modification de KeyError dans une classe dérivée de dict


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre Expert

    Homme Profil pro
    Ingénieur calcul scientifique
    Inscrit en
    Mars 2013
    Messages
    1 229
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur calcul scientifique

    Informations forums :
    Inscription : Mars 2013
    Messages : 1 229
    Par défaut Modification de KeyError dans une classe dérivée de dict
    Je souhaite dériver une classe de dictionnaire pour lui ajouter de la sémantique. Admettons, j'ai un dictionaire contenant des configurations, chaque config portant un nom, les noms etant les clés du dico. Pour être plus clair vis à vis de mon utilisateur, s'il me demande une clé qui n'est pas dans le dico, je veux lui soulever une exception plus explicite qu'un KeyError. Je procède ainsi :

    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
    class UnexistantConfigError(KeyError): pass
     
    class Configs(dict):
        def __getitem__(self, i):
            try :
                return super(Configs, self).__getitem__(i)
            except KeyError :
                raise UnexistantConfigError("%s is an unknown configuration"%i)
            except Exception as e :
                raise e
     
    class ConfigA(): pass
    class ConfigB(): pass
     
    configs = Configs( { "1" : ConfigA, "2" : ConfigB } )
     
    print(configs["3"]) ### OK : Raise UnexistantConfigError
    Ca fonctionne bien, et ca fait le job voulu. Maintenant la question est : y a t il un moyen plus propre de faire cela ? Un moyen sans devoir réécrire le __getitem__ ?

  2. #2
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 835
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 835
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par lg_53 Voir le message
    Maintenant la question est : y a t il un moyen plus propre de faire cela ?
    Supprimer ce except Exception as e : raise e qui signifie littéralement "intercepte toute autre exception pour la renvoyer comme une exception" (pourquoi alors l'intercepter ???).
    Et peut-être si ton "UnexistantConfigError" est juste une exception liée à ton "Configs", l'intégrer alors comme sous-classe de "Configs"...

    Citation Envoyé par lg_53 Voir le message
    Un moyen sans devoir réécrire le __getitem__ ?
    Pas à ma connaissance. Il me semble qu'on peut redéfinir des trucs élémentaires (comme les int, les str, etc) en jouant avec __new__ mais je ne sais pas le faire. Et est-ce que cela permettrait de supprimer ton __getitem__ (qui est quand-même nécessaire pour que ton objet puisse être invoqué via un appel avec indices) ?
    Donc me semble que ta solution est déjà pas mal. Bon effectivement tu réécris le __getitem__ mais bon, Python est un beau langage mais qui nécessite tout de même parfois quelques concessions à la trop grande facilité.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  3. #3
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 741
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 741
    Par défaut
    Salut,

    Citation Envoyé par lg_53 Voir le message
    Un moyen sans devoir réécrire le __getitem__ ?
    Surcharger une méthode pour en modifier le comportement (ici en attrapant l'exception levée pour la remplacer par une autre) est "normal".
    Le soucis est qu'on ne la remplace pas: on en ajoute une autre.
    Pourquoi ne pas juste "customiser" le message d'erreur:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
        def __getitem__(self, i):
            try :
                return super(Configs, self).__getitem__(i)
            except KeyError as e:
                e.args = ("%s is an unknown configuration"%i,)
                raise
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  4. #4
    Membre Expert

    Homme Profil pro
    Ingénieur calcul scientifique
    Inscrit en
    Mars 2013
    Messages
    1 229
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur calcul scientifique

    Informations forums :
    Inscription : Mars 2013
    Messages : 1 229
    Par défaut
    Citation Envoyé par Sve@r
    Supprimer ce except Exception as e : raise e qui signifie littéralement "intercepte toute autre exception pour la renvoyer comme une exception" (pourquoi alors l'intercepter ???)
    C'est pas faux !


    Citation Envoyé par wiztricks
    Pourquoi ne pas juste "customiser" le message d'erreur:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
        def __getitem__(self, i):
            try :
                return super(Configs, self).__getitem__(i)
            except KeyError as e:
                e.args = ("%s is an unknown configuration"%i,)
                raise
    Hehe, un point de la doc que j'avais oublié : l'attribut args des exceptions (faut dire que je ne m'en suis jamais servi).


    Vos 2 remarques me permettent de raccourcir un peu mon code. Bon ceci dit ca reste bien long pour une si petite fonctionalité. J'avais espéré qqch de plus efficace... Comme tu dis Sve@r, on ne peut pas gagner sur tous les tableaux.

    Merci à vous deux.

  5. #5
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2009
    Messages
    4 493
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 493
    Billets dans le blog
    1
    Par défaut
    En fait, je ne vois pas trop ce qui ne te va pas dans ton code.

    Tu étends une classe, tu souhaites adapter le comportement d'une méthode, tu le fais. C'est exactement le principe d'overrider une fonction de la classe mère dans une classe fille.

    Tout va bien, non ?

  6. #6
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 835
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 835
    Billets dans le blog
    1
    Par défaut
    En dehors de la solution de wiztricks, ne peut-on pas remplacer class UnexistantConfigError(KeyError): pass par un plus simple UnexistantConfigError=KeyError ?
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  7. #7
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 741
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 741
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    ne peut-on pas remplacer class UnexistantConfigError(KeyError): pass par un plus simple UnexistantConfigError=KeyError ?
    On peut toujours le faire, mais çà ne changera pas le libellé de l'exception qui sera toujours KeyError.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. HDN_ITEMCLICK dans une classe dérivée
    Par fantomchris dans le forum MFC
    Réponses: 5
    Dernier message: 17/07/2008, 16h08
  2. préciser le type des objets dans une classe dérivée d'arraylist
    Par JCD21 dans le forum Collection et Stream
    Réponses: 4
    Dernier message: 28/06/2008, 18h04
  3. Réponses: 8
    Dernier message: 17/04/2007, 11h35
  4. Réponses: 4
    Dernier message: 17/03/2007, 01h06
  5. problème d'accès dans une classe dérivée!
    Par chrono23 dans le forum C++
    Réponses: 47
    Dernier message: 10/10/2006, 11h22

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