views:

119

answers:

3

I have several decorators on each function, is there a way to pack them in to one instead?

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

change to:

@all_funs #runs fun1 fun2 and fun3, how should all_funs look like?
def do_stuf():
    pass
A: 
def all_funs(f):
    return fun1(fun2(fun3(f)))
nailxx
+7  A: 

A decorator is in principle only syntactic sugar for this:

def do_stuf():
    pass

do_stuf = fun1(do_stuf)

So in your all_fun, all you should need to do is to wrap the function in the same kind of chain of decorators:

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

Things get a little bit (but only a litte) more complex if you have parameters to the decorators.

Lennart Regebro
+5  A: 

It's also possible to write a generic decorator that supports decorator chaining:

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
Torsten Marek