Most examples of creating decorators in python, show a function returning an inline function. If you wanted to initialize the decorator in some way, you'd have to write a function, initializing a function, returning a function.

When you manage to wrap your head around it, it's not even that complicated, but the combination of three levels of nested functions and scope was confusing to me at first.

I had a eureka moment, when I realized that a decorator could be any callable. So a class implementing __call__ would suffice.

Again, this probably falls into the personal preference category, but separating the initializing code into a __init__ method and the wrapping code into a __call__ method, made it a lot clearer to me.

An example:

class MyDecorator(object):
    """ this decorator prints a custom msg before executing """
    def __init__(self, msg):
        """ initialize decorator """
        self.msg = msg

    def __call__(self, func):
        """ wrap function with _wrapper function """
        def _wrapper(*args, **kwargs):
            print self.msg
            return func(*args, **kwargs)

        return _wrapper

This simple class-based decorator, can now be used as followed:

@MyDecorator("Hello")
def test(name):
    print name

The output will be:

    >>> test("gumuz")
    Hello
    gumuz

I hope someone thought this was as insightful as I found it to be. In the next post I will show you how to create a more useful decorator using classes and class-variables.

blog comments powered by Disqus