2010-02-02 16 views
10

Tengo varios decoradores en cada función, ¿hay alguna manera de incluirlos en uno?¿Cómo puedo empacar varios decoradores en uno?

@fun1 
@fun2 
@fun3 
def do_stuf(): 
    pass 

cambio a:

@all_funs #runs fun1 fun2 and fun3, how should all_funs look like? 
def do_stuf(): 
    pass 
+0

duplicado: http://stackoverflow.com/questions/2094008/why-cant-python-decorators-be-chained-across -definitions –

+2

@ S.Lott: No lo es. –

+0

@Torsten Marek: ¿Algún razonamiento o evidencia para ese reclamo? –

Respuesta

7

También es posible escribir un decorador genérico que soporta el encadenamiento de decorador:

def fun1(f): 
    print "fun1" 
    return f 

def fun2(f): 
    print "fun2" 
    return f 

def fun3(f): 
    print "fun3" 
    return f 

def chained(*dec_funs): 
    def _inner_chain(f): 
     for dec in reversed(dec_funs): 
      f = dec(f) 
     return f 

    return _inner_chain 

@fun1 
@fun2 
@fun3 
def do_stuff(): 
    pass 

@chained(fun1, fun2, fun3) 
def do_stuff2(): 
    pass 

all_funs = chained(fun1, fun2, fun3) 

@all_funs 
def do_stuff3(): 
    pass 
1
def all_funs(f): 
    return fun1(fun2(fun3(f))) 
11

Un decorador es, en principio, sólo el azúcar sintáctica para esto:

def do_stuf(): 
    pass 

do_stuf = fun1(do_stuf) 

Así que en su all_fun, todo lo que necesitará hacer es para envolver la función en el mismo tipo de cadena de decoradores:

def all_funs(funky): 
    return fun1(fun2(fun3(fun4(funky))) 

Las cosas se ponen un poco (pero solo un poco) más complejas si tiene parámetros para los decoradores.

Cuestiones relacionadas