Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to group decorators in Python

In Flask I'm using a set of decorators for each route, but the code is "ugly":

@app.route("/first")
@auth.login_required
@crossdomain(origin='*')
@nocache
def first_page:
    ....

@app.route("/second")
@auth.login_required
@crossdomain(origin='*')
@nocache
def second_page:
    ....

I would prefer to have a declaration that groups all of them with a single decorator:

@nice_decorator("/first")
def first_page:
    ....

@nice_decorator("/second")
def second_page:
    ....

I tried to follow the answer at Can I combine two decorators into a single one in Python? but I cannot make it working:

def composed(*decs):
    def deco(f):
        for dec in reversed(decs):
            f = dec(f)
        return f
    return deco

def nice_decorator(route):
    composed(app.route(route),
             auth.login_required,
             crossdomain(origin="*"),
             nocache)

@nice_decorator("/first")
def first_page:
    ....

because of this error that I don't understand:

@nice_decorator("/first")
TypeError: 'NoneType' object is not callable

Following one of the comments I defined it with another form that works but without the possibility to specify the route parameter:

new_decorator2 = composed(app.route("/first"),
                          auth.login_required,
                          crossdomain(origin="*"),
                          nocache)

Is it possible to define a single decorator with parameters?

like image 524
Alex Poca Avatar asked Oct 04 '17 12:10

Alex Poca


People also ask

Can you chain decorators in Python?

Chaining decorators means applying more than one decorator inside a function. Python allows us to implement more than one decorator to a function. It makes decorators useful for reusable building blocks as it accumulates several effects together. It is also known as nested decorators in Python.

Can a function have two decorators?

This is to say, a function can be decorated multiple times with different (or same) decorators.

How do class decorators work in Python?

Decorators are a very powerful and useful tool in Python since it allows programmers to modify the behaviour of function or class. Decorators allow us to wrap another function in order to extend the behaviour of the wrapped function, without permanently modifying it.

How are decorators used in Python?

You'll use a decorator when you need to change the behavior of a function without modifying the function itself. A few good examples are when you want to add logging, test performance, perform caching, verify permissions, and so on. You can also use one when you need to run the same code on multiple functions.


1 Answers

You're not defining the composition correctly. You need to change the definition of nice_decorator to something like this:

def nice_decorator(route):
    return composed(
        app.route(route),
        auth.login_required,
        crossdomain(origin="*"),
        nocache
    )

Your previous version never actually returned anything. Python isn't like Ruby or Lisp where the last expression is the return value.

like image 191
Edward Minnix Avatar answered Oct 19 '22 11:10

Edward Minnix