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 :

une méthode qui sert de décorateur


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé Avatar de sopsag
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    224
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2008
    Messages : 224
    Par défaut une méthode qui sert de décorateur
    Bonjour,

    j'aimerais savoir s'il est possible d'utiliser une méthode pour décorer une autre méthode.
    Voici un bout de code (d'exemple, mon vrai code est + compliqué) pour éclaircir mon truc :
    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
    class Spam :
     
        def __init__(self,verbose):
            self.verbose = verbose
            self.name = 'Spam'    
     
        def deco ( self,func ):
            if self.verbose: # NB j'accède au self de l'instance
                def sub ( *k,**a ):
                    print 'entering',self.name
                    return func( *k,**a )  # execute la methode
            else:
                def sub ( *k,**a ):
                    return func( *k,**a )  # execute la methode
            return sub
     
        @deco
        def eggs (self,x):
            return x+1
     
    s = Spam(True)
    x = s.eggs(5)
    Voici le code que j'imagine pour mon cas, mais ça ne compile pas : "deco() takes exactly 2 arguments (1 given)"

    J'ai essayé toutes sortes de solutions de contournement, mais rien ne passe...
    (déclarer deco en @staticmethod, décorer eggs avec @self.deco, etc.)

    Bien sûr, je pourrais déclarer deco comme une fonction en dehors de Spam, mais ce serait moche car le code de deco est très lié à la classe Spam (ici, j'ai mis un code rikiki pour l'exemple)...

    Attention : ce bout de code est là pour l'exemple... le but n'est pas de trouver comment faire marcher cet exemple, mais de trouver comment accéder au self de l'instance dans le décorateur.

    Si quelqu'un a une idée...
    merci d'avance !

  2. #2
    Membre éclairé
    Avatar de airod
    Homme Profil pro
    Gérant Associé, DMP Santé et Directeur technique
    Inscrit en
    Août 2004
    Messages
    767
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Gérant Associé, DMP Santé et Directeur technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 767

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

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

    Informations forums :
    Inscription : Février 2007
    Messages : 574
    Par défaut
    Salut,
    Je passerai par une nested class. Par contre tu n'auras accès qu'aux méthodes statiques de ta classe externe, ce qui semble être limitant pour toi :
    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
     
    class test(object):
     
      a_string = "a_string"
     
      class decorator(object):
     
        def __init__(self, func):
          self.func = func
          print test.a_string
     
        def __call__(self, *args, **kwargs):
          print "Entering function %s" % self.func.__name__
          self.func(test.__class__, *args, **kwargs)
          print "Exiting function %s" % self.func.__name__
     
      def __init__(self):
        print "new object"
     
      @decorator
      def do_some(self, *args, **kwargs):
        print "doing something %s %s" % (args, kwargs)
     
    if __name__ == "__main__":
      t = test()
      t.do_some("fun", "run")
    Je sais pas si ça va te convenir.

  4. #4
    Membre confirmé Avatar de sopsag
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    224
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2008
    Messages : 224
    Par défaut
    Merci airod, mais dans ces exemples, il n'y a des méthodes décorées, mais pas de méthodes "décoratrices"...

    Merci dahtah, mais comme tu l'as deviné, ça ne me suffit pas, car je veux accéder au self (= membres d'instance et pas seulement de classe).

    D'ailleurs, une classe imbriquée peut elle voir le self de sa classe imbriquante ?

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

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

    Informations forums :
    Inscription : Février 2007
    Messages : 574
    Par défaut
    Citation Envoyé par sopsag Voir le message
    D'ailleurs, une classe imbriquée peut elle voir le self de sa classe imbriquante ?
    Non, à moins que l'on passe l'instance de classe imbriquante au constructeur de la classe imbriquée. Et encore cela pose des problèmes dans les appels :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    self.classe_imbriquante.methode()
    car en fait on passe l'instance de la classe imbriquée à la méthode appelée (methode())et non l'instance de la classe imbriquante.

    Je crois que là le plus simple sera de mettre ta méthode décoratrice à l'extérieur de ta classe.
    Bon courage

  6. #6
    Membre Expert
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 941
    Par défaut
    Le premier problème est que le décorateur est exécuté lors de la création de la classe, et pas de l'instance, donc il n'est pas possible d'accéder à self dans le décorateur.
    Ma première tentative a donc été:
    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
    class Spam :
        def __init__(self,verbose):
            self.verbose = verbose
            self.name = 'Spam'    
     
        @staticmethod
        def deco(func):
            def sub (self, *k, **a):
                if self.verbose: # NB j'accède au self de l'instance
                    print 'entering', self.name
                return func(self, *k, **a)  # execute la methode
            return sub
     
        @Spam.deco
        def eggs(self,x):
            return x+1
     
    s = Spam(True)
    x = s.eggs(5)
    Mais cela ne fonctionne pas:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    TypeError: unbound method deco() must be called with Spam instance as first argument (got function instance instead)
    Bizarre que Spam.deco soit vue comme une unbound method alors que c'est censé être une méthode statique... C'est sans doute lié à la façon donc la classe est construite.

    Par contre ceci, qui semble un peu étrange, 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
    class Spam :
        def __init__(self,verbose):
            self.verbose = verbose
            self.name = 'Spam'    
     
        def deco(func):
            def sub (self, *k, **a):
                if self.verbose: # NB j'accède au self de l'instance
                    print 'entering', self.name
                return func(self, *k, **a)  # execute la methode
            return sub
     
        @deco
        def eggs(self,x):
            return x+1
     
    s = Spam(True)
    x = s.eggs(5)
    Dans ce cas, je pense que '@deco' appelle en réalité la fonction deco, qui sera promue en méthode d'instance au sein de la classe.

    Mais en réalité, ce n'a plus aucun intérêt de faire du décorateur une méthode, autant en faire une gentille fonction en dehors de la classe.

    [EDIT]
    Ceci fonctionne aussi et est peut-être un peu plus propre, mais toujours aussi inutile:
    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
    class Spam :
        def __init__(self,verbose):
            self.verbose = verbose
            self.name = 'Spam'    
     
        def deco(func):
            def sub (self, *k, **a):
                if self.verbose: # NB j'accède au self de l'instance
                    print 'entering', self.name
                return func(self, *k, **a)  # execute la methode
            return sub
     
        @deco
        def eggs(self,x):
            return x+1
     
        deco = staticmethod(deco)
     
    s = Spam(True)
    x = s.eggs(5)

Discussions similaires

  1. une méthode qui retourne une valeur
    Par soujava dans le forum Débuter avec Java
    Réponses: 8
    Dernier message: 17/04/2008, 14h29
  2. [JDOM] Une méthode qui ne marche pas
    Par kaninama dans le forum Format d'échange (XML, JSON...)
    Réponses: 1
    Dernier message: 24/05/2006, 16h10
  3. Réponses: 12
    Dernier message: 23/03/2006, 14h13
  4. Suppression de cadre autour d'une image qui sert de lien
    Par vasilov dans le forum Balisage (X)HTML et validation W3C
    Réponses: 3
    Dernier message: 03/04/2005, 13h02
  5. une méthode qui écrit dans la sortie html ?
    Par iubito dans le forum Servlets/JSP
    Réponses: 2
    Dernier message: 03/12/2003, 15h34

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