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 :

Heritage et decorateur


Sujet :

Python

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Avril 2008
    Messages
    35
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Avril 2008
    Messages : 35
    Points : 35
    Points
    35
    Par défaut Heritage et decorateur
    bonjour a tous,

    je souhaiterais utiliser le DP singleton en Python, et apres quelque recherche, j'ai pu trouver une methode elegante utilisant les decorator :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    def singleton(cls):
        instances = {}
        def getInstance():
            if cls not in instances:
                instances[cls] = cls()
            return instances[cls]
        return getInstance
     
    @singleton
    class myClass:
        pass
    Cependant imaginez la situation suivante : j'ai une classe mere, et plusieurs classes filles. Je voudrais donc que mon principe du singleton s'applique a toutes les classes filles. J'ai donc tendance a mettre le @singleton sur la classe mere.
    Malheureusement, l'heritage devient impossible :
    TypeError: Error when calling the metaclass bases
    function() argument 1 must be code, not str
    Apres quelques recherches, il s'avere que c'est parce que ma classe mere devient une fonction aux yeux de Python. Et allez dire a python que je veux heriter d'une fonction...

    Est ce qu'il y a une maniere elegante de contourenr le probleme, ou alors est ce que je vais devoir placer le @singleton sur chaque classe fille?

    Merci

  2. #2
    Membre éprouvé
    Homme Profil pro
    Inscrit en
    Décembre 2007
    Messages
    758
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations professionnelles :
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Décembre 2007
    Messages : 758
    Points : 970
    Points
    970
    Par défaut
    bonsoir,

    sans passer par le décorateur, je te suggère de surcharger la méthode __new__ de la classe de base (elle même devant dériver directement ou indirectement de object).

    on ajoute un attribut à la classe, un drapeau qui change de valeur si une instance est crée. le __new__ surchargé doit permettre de créer l'instance et de lever une exception si le drapeau est déjà utilisé.

    avec cette solution, plus de soucis avec l'héritage par contre tu n'auras qu'une seule instance pour tous les types (et pas une par type)

  3. #3
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Avril 2008
    Messages
    35
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Avril 2008
    Messages : 35
    Points : 35
    Points
    35
    Par défaut
    Citation Envoyé par kango Voir le message
    avec cette solution, plus de soucis avec l'héritage par contre tu n'auras qu'une seule instance pour tous les types (et pas une par type)
    Tu veux dire que je ne pourais avoir qu'une seule instance de toute mes sous classes reunies (au lieu de 1 instance par sous classe) ?

    Ca, ca serait tres embetant

    De plus, avec cette methode de drapeau, je vois difficilement comment je peux recuperer l'instance deja creee... J'aurais simplement une exception disant "attention il y a deja une instance!"

    Ou alors j'ai mal compris quelque chose

    De plus, ca me forcerait a surcharger les methodes __new__ de toutes les classes que je voudrais en singleton... pas top ca non plus

    Merci pour le coup de main en tout cas

  4. #4
    Membre éprouvé
    Homme Profil pro
    Inscrit en
    Décembre 2007
    Messages
    758
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations professionnelles :
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Décembre 2007
    Messages : 758
    Points : 970
    Points
    970
    Par défaut
    Citation Envoyé par Haenou Voir le message
    Tu veux dire que je ne pourais avoir qu'une seule instance de toute mes sous classes reunies (au lieu de 1 instance par sous classe) ?
    oui

    Citation Envoyé par Haenou Voir le message
    De plus, avec cette methode de drapeau, je vois difficilement comment je peux recuperer l'instance deja creee... J'aurais simplement une exception disant "attention il y a deja une instance!"
    non, tu peux faire en sorte que la méthode __new__ te retourne l'instance déjà existante, c'est en fait l'interêt de passer par __new__ plutôt que par init

    Citation Envoyé par Haenou Voir le message
    De plus, ca me forcerait a surcharger les methodes __new__ de toutes les classes que je voudrais en singleton... pas top ca non plus
    ça forcément , mais je croyais que tu voulais que ce comportement soit toujours disponible en héritant de la classe, là tu veux explicitement que ce comportement ne soit pas transmis.

    si tu veux avoir quelquechose de moins "copier-coller" pour effectuer ce genre d'actions, il peut être envisagé de passer par une métaclasse.

    ceci peut t'interesser:

    http://code.activestate.com/recipes/...s-a-metaclass/

  5. #5
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Avril 2008
    Messages
    35
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Avril 2008
    Messages : 35
    Points : 35
    Points
    35
    Par défaut
    Citation Envoyé par kango Voir le message
    ça forcément , mais je croyais que tu voulais que ce comportement soit toujours disponible en héritant de la classe, là tu veux explicitement que ce comportement ne soit pas transmis.
    Pardon, je me suis mal exprime, en fait je parlais d'autres classes, pas du tout en rapport avec cette hierarchie ci

    Citation Envoyé par kango Voir le message
    Je vais voir ce lien de suite . La metaprog, je connais bien en theorie, mais alors l'application a Python.... (forcement, en etant nouveau en python... )

    Merci encore

  6. #6
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 281
    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 281
    Points : 36 768
    Points
    36 768
    Par défaut
    salut,

    Cependant imaginez la situation suivante : j'ai une classe mere, et plusieurs classes filles. Je voudrais donc que mon principe du singleton s'applique a toutes les classes filles.
    Dit autrement, lorsqu'on écrit:
    a = Fille()
    cela doit retourner la même instance de 'fille'.

    Souvenez vous qu'un Singleton fonctionne parce qu'il cache l'instance déjà créée dans une variable de classe. i.e. la déclaration de 'Fille' pourrait être:
    class _Fille():
    _instance = None
    ...
    La methode getInstance du Singleton est une factory: elle contrôle que l'objet qui vous est retourné est le 'bon'. C'est en général une méthode 'static' puisqu'elle doit créer l'instance...

    Python est 'battery included', vous avez une fonction factory déjà toute prête, la méthode __call__ qui est appelée un peu comme __init__ style:

    a = _Fille(), exécute __init__
    a = _Fille()(), exécute __init__ puis __call__

    Ajoutons la déclaration:
    Fille = _Fille()
    et
    a = Fille() appellera __call__

    Maintenant que la mécanique est un peu décrite... Un peu de code
    Code Python : 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
    class Mom(object):
        def __init__(self, name):
            assert not hasattr(self.__class__,'_instance')
            setattr(self.__class__,'_instance', self)
            self.name = name
     
        def __call__(self): 
            assert hasattr(self.__class__,'_instance')
            return getattr(self.__class__,'_instance')
     
        def __str__(self):
            klass = self.__class__.__name__
            name  = self.name
            return 'class %(klass)s: %(name)s' % vars()
     
    class _Child1(Mom):
        def __init__(self, name):
            super(self.__class__, self).__init__(name)
     
    class _Child2(Mom):
        def __init__(self, name):
            super(self.__class__, self).__init__(name)
     
     
    Child1 = _Child1('factory')
    print 'Child1: ', Child1
    Child2 = _Child2('factory')
    print 'Child2: ', Child2
     
    a = Child1()
    print 'a: ', a
    b = Child2()
    print 'b: ', b

    Cool non?
    - W
    PS: la réponse est non!!!
    La chose écrite en Python est beaucoup moins bavarde...
    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
    class Borg(object):
        __shared_state = {}
        def __init__(self):
            self.__dict__ = self.__shared_state
        def __str__(self):
            klass = self.__class__.__name__
            name  = self.name
            return 'class %(klass)s: %(name)s' % vars()
     
    class Child1(Borg):
        def __init__(self, name):
            super(self.__class__, self).__init__()
            self.name = name
     
    class Child2(Borg):
        def __init__(self, name):
            super(self.__class__, self).__init__()
            self.name = name
     
    a = Child1('a')
    print 'a: ', a
    b = Child2('b')
    print 'b: ', b
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  7. #7
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Avril 2008
    Messages
    35
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Avril 2008
    Messages : 35
    Points : 35
    Points
    35
    Par défaut
    Ohla . Va me falloir un peu de temps pour digerer tout ca et bien maitriser tout ces concepts, mais effectivement, ca m'a l'air bien cool
    Merci

  8. #8
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 281
    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 281
    Points : 36 768
    Points
    36 768
    Par défaut
    Salut,

    Citation Envoyé par Haenou Voir le message
    Ohla . Va me falloir un peu de temps pour digerer tout ca et bien maitriser tout ces concepts, mais effectivement, ca m'a l'air bien cool
    Merci

    Lorsque vous aurez digéré... essayer de jeter un œil à: http://www.developpez.net/forums/d91...reinitialiser/
    vous y trouverez une troisième forme de réalisation de "Singleton" fondée sur les modules (et non les classes) et complètement étrangère à la doxa POO.

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

Discussions similaires

  1. heritage des contraintes
    Par krimson dans le forum PostgreSQL
    Réponses: 3
    Dernier message: 30/04/2004, 12h04
  2. [Kylix] heritage multiple et interfaces :(
    Par le_barbu dans le forum EDI
    Réponses: 4
    Dernier message: 26/01/2004, 19h30
  3. [Postgres] Pb d'heritage...
    Par anonia dans le forum PostgreSQL
    Réponses: 1
    Dernier message: 23/08/2003, 22h34
  4. [HERITAGE] Redondance ou pas redondance ???
    Par cyrillus76 dans le forum Schéma
    Réponses: 1
    Dernier message: 11/06/2003, 09h46
  5. [PostgreSQL] Question vis a vis de l'heritage...
    Par Gandalf dans le forum PostgreSQL
    Réponses: 2
    Dernier message: 12/05/2003, 16h53

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