A quick introduction to Python decorators

Decorators were introduced in Python 2.4 to provide a clean syntax for function wrappers. New syntax was not only applied to already existing Python built-in wrappers, but also enabled programmers to elegantly wrap any function or method with additional functionality.

According to the Python Glossary, a decorator is a function returning another function. This is a pretty vague description, so maybe it’s best to take a look at some code.

Next few lines describe how a decorator body looks like in general case:

def decorator_name(function):
    def wrapper(*args):
        # 1. Do some preprocessing.
        # ...

        # 2. Call 'function' with given arguments.
        function(*args)

        # 3. Do some postprocessing.
        # ...
    return wrapper

Bear in mind that the wrapper function must have the same signature as the decorated function. To be able to decorate any function, the template wrapper takes a tuple of non-keyword arguments (*args). Now, all that’s left is to actually apply the decorator:

@decorator_name
def some_func():
    pass

Keep in mind that this is equivalent to:

def some_func():
    pass
some_func = decorator_name(some_func)

So, the basic idea is simple – a decorator gives us an opportunity to do something before and after the decorated function gets called. Several simple examples are due:
1. Timing. To see how much time your functions consume, check the clock before and after the call, then print the difference:

import time

def timed(some_function):
    def wrapper(*args):
        start = time.clock()
        result = some_function(*args)
        end = time.clock()
        print some_function.func_name, end - start
    return wrapper

2. Printing and logging. Function arguments can easily be printed to console or logged to a file with decorators; same approach can be applied to return values. Decorator arguments can be used to divert logging to a different path without changing the decorator itself.
3. Debugging. You can check/assert argument values or types before the original function call. Note, however, that using isinstance() is usually discouraged (duck typing, remember?:).

Of course, this is just a tiny bit of all possible decorator uses. Make sure you check out Python Wiki for more examples and some inspiration.

About Matej Salković

Matej is a C++ programmer currently working on cross-platform CAD applications in Python.
This entry was posted in Blog. Bookmark the permalink.

2 comments

  1. Pingback: Decorators em Python | Klaus Laube

  2. Pingback: Decorators em Python | Profissionais TI - Pra quem respira informação

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>