2010-11-08 3 views
4

Étant donné une liste de méthodes de décorateur, comment les appliquer à un appelable?Appliquer une liste de décorateurs à un appelable?

Par exemple, depuis:

@foo 
@bar 
def baz(): 
    pass 

... est le même que:

def baz(): 
    pass 
baz = foo(bar(baz))) 

... on peut supposer que la liste des décorateurs ([foo, bar]) elles pourraient être appliquées à baz dynamiquement.

+0

"on peut supposer que"? Vraiment? Basé sur quoi? Qu'est-ce qui vous amène à cette conclusion? –

+2

@ S.Lott Parce que c'est Python? Mon hypothèse générale est que je peux faire à peu près tout ce que je veux. – aaronasterling

+0

@aaronasterling, je pense que vous confondez Python avec le langage informatique mythique [DWIM] (http://en.wikipedia.org/wiki/DWIM). – martineau

Répondre

11

Avec encore un autre décorateur!

def yad(decorators): 
    def decorator(f): 
     for d in reversed(decorators): 
      f = d(f) 
     return f 
    return decorator 

Exemple d'utilisation

list_of_decorators = [foo, bar] 

@yad(list_of_decorators) 
def foo(): 
    print 'foo' 

Sans la syntaxe de décorateur, il ressemblerait

func = yad(list_of_decorators)(func) 

Si vous voulez appliquer la même liste à plusieurs fonctions, vous pouvez le faire comme:

dec = yad(list_of_decorators) 

func1 = dec(func1) 

@dec 
def func2(): 
    pass 

Comme les points récursifs dans les commentaires, vous pouvez définir yad (je suis sûr qu'il y a un meilleur nom pour cela) pour accepter *decorators au lieu de decorators. Ensuite, vous n'avez pas besoin d'utiliser des crochets si vous créez la liste in situ. La façon dont j'ai démontré est préférable si la liste est créée ailleurs.

+3

Si vous définissez yad avec ceci: 'def yad (* decorators):', alors vous pouvez éviter les parenthèses de liste. – recursive

+0

@recursive C'est comme ça que je l'ai eu à l'origine mais ensuite j'ai vu que OP utilisait des parenthèses et que la liste pouvait être construite ailleurs (d'où l'accent mis sur ne pas utiliser la syntaxe du décorateur). Bonne mention cependant. – aaronasterling

+0

merci, je suis allé avec une simple boucle: 'pour inversé (décorateurs): baz = d (baz)' –

2

Avec un classique alltime:

def compose(f, g): 
    def composed(*a, **k): 
     return g(f(*a, **k)) 
    return composed 

@compose(foo, compose(bar, baz)) 
def blam(): 
    pass 
Questions connexes