Home > Programming, Python > Python decorators

Python decorators

March 20th, 2009

I have a project at work where in Python, where I use decorators to wrap functionality for views. I hit on a snag when I used 2 decorators on 1 function. I like using class decorators, I read some recommendations regarding that, and it fits better with my Java upbringing :) . The 2 decorators I needed to apply to the same function looked like this (__call__ method omitted for brevity):

1
2
3
4
5
6
7
8
9
class AutoTemplate(object):
    def __init__(self, func):
        self.func = func
        pathElems = func.__module__.split(".")[:-1]+["%s.html"%func.__name__]
        self.template = os.path.join(* pathElems)
 
class AccessRequired(object):
    def __init__(self, func):
        self.func = func

In addition, I used the functions actual name in the urls.py file to generate the url tuple:

1
2
3
def createUrl(method):
    name = method.func.func_name
    return (r'^%s.html$'%name, method, {}, name)

So the finished product after decorators where applied needed to work for that. Because the decorators resulted in a class rather than a function being assigned to the the view, this didn’t work properly.

With a little help from Stackoverflow however, I came upon a good solution, that makes it really transparent that a function is actually decorated:

1
2
3
4
5
6
7
8
class DecoratorBase(object):
    def __init__(self, func):
        self.func = func
        for n in set(dir(func)) - set(dir(self)):
            setattr(self, n, getattr(func, n))
 
class AutoTemplate(DecoratorBase): pass
class AccessRequired(DecoratorBase): pass

This does not work for decorators requiring parameters, I will see if I can find a solution for that if I need it.

Staale Programming, Python ,