2009-04-01 6 views
3

Existe-t-il un moyen d'écrire des décorateurs dans une structure de classe qui s'intègre bien? Par exemple, cela fonctionne très bien sans cours:Décorateurs et dans la classe

def wrap1(func): 
    def loc(*args,**kwargs): 
     print 1 
     return func(*args,**kwargs) 
    return loc 

def wrap2(func): 
    def loc(*args,**kwargs): 
     print 2 
     return func(*args,**kwargs) 
    return loc 


def wrap3(func): 
    def loc(*args,**kwargs): 
     print 3 
     return func(*args,**kwargs) 
    return loc 

def merger(func): 
    return wrap1(wrap2(wrap3(func))) 


@merger 
def merged(): 
    print "merged" 


@wrap1 
@wrap2 
@wrap3 
def individually_wrapped(): 
    print "individually wrapped" 

merged() 
individually_wrapped() 

La sortie est:

1 
2 
3 
merged 
1 
2 
3 
individually wrapped 

qui est ce que je veux. Mais maintenant disons que je veux faire merged et individually_wrapped comme méthodes statiques ou de classe. Cela fonctionnera également, tant que les décorateurs sont tenus à l'écart de l'espace de nom de classe. Y at-il un bon moyen de mettre les décorateurs dans l'espace de noms? Je préfère ne pas énumérer toutes les façons qui ne fonctionneront pas, mais le problème principal est que si merger est une méthode, il ne peut pas accéder aux méthodes wrapX. Peut-être que c'est une chose stupide à vouloir faire, mais quelqu'un at-il quelque chose comme ça à travailler, avec tous les décorateurs et méthodes décorées dans la même classe?

Répondre

5

"Yat-il un bon moyen de mettre les décorateurs dans l'espace de noms?"

Il n'y a pas de raison impérieuse pour cela. Vous avez des fichiers de module. Ce sont un conteneur bien rangé pour une classe et quelques décorateurs.

Vous n'avez jamais besoin de décorateurs comme méthodes de classe - vous pouvez simplement appeler une méthode d'une autre.

+0

Je pense que c'est la voie à suivre, il n'y a pas de raison de les garder en classe –

2

En fait, il ne devrait y avoir aucun problème à les placer tous dans une classe. A l'intérieur d'un corps de classe, vous pouvez nommer une variable définie jusqu'à présent simplement en le nommant:

 
class A(object): 
    a = 1 
    b = 2 
    c = a + b 

print A.c 

Cela donne le résultat 3, car si Python exécute un corps de classe les fonctions peuvent « voir » les variables d'un et b qui ont été déclarés. Donc, ce qui suit fonctionne également:

 
class B(object): 
    @staticmethod 
    def wrapper(*args, **kw): 
     ... 

    @wrapper 
    def a(...): 
     ... 

Maintenant, qu'en est-il de votre fonction de fusion? Le problème est que la fonction wrapper s'exécute longtemps après le corps de la classe est en cours d'exécution et les variables qu'il a définies ne sont plus dans la portée englobante. Comment pouvez-vous vous y référer, alors? En utilisant le nom de la classe comme préfixe! Comme ceci:

 
class C(object): 
    @staticmethod 
    def wrap1(*args, **kw): 
     ... 
    @staticmethod 
    def wrap2(*args, **kw): 
     ... 
    @staticmethod 
    def wrap3(*args, **kw): 
     ... 
    @staticmethod 
    def merger(*args, **kw): 
     C.wrap1(C.wrap2(C.wrap3(...))) 

    @merger 
    def plain(...): 
     ... 

La règle générale avec Python est: code qui passe juste au niveau du corps de classe peut parler de toutes les variables et les méthodes qui ont été définies jusqu'à présent à l'intérieur de celui-ci, et ce moyen vous pouvez utiliser ces variables de classe en tant que wrappers. Mais une fois que vous êtes à l'intérieur d'une fonction dans la classe, que ce soit une fonction de classe, une fonction statique ou une méthode (et cette classe est une méthode de classe puisqu'elle prend des arguments mais pas de self), vous devez utiliser le nom de la classe pour "obtenir" son contenu

+0

Bon point Si je dois me référer à la classe par son nom pour le faire, il n'y a peut-être pas de bonne raison de les mettre dans la classe –

+0

Oui, il n'y aurait peut-être pas de raison de le faire de cette façon, si vous essayiez simplement de vous y référer plus facilement. les wrappers en dehors de la classe, alors ils peuvent être "vus" à la fois dans la définition de la classe et dans n'importe laquelle de ses fonctions. –

Questions connexes