Decorators

In general, decorators are functions that manipulate functions. More specifically, a decorator wraps a function to manage a function call.

Imagine you have the a Python function::

def addition(a, b):
    """add two arguments a,b and returns the result"""
    return a + b

If you now want to add functionality, e.g. printing a timestamp for every addition, you could define a new function:

import time

def addition_with_timestamp(a, b):
    print(time.asctime())
    return addition(a, b)

If you want to add the timestamp feature to many functions, consider using a decorator:

def print_timestamp(func):
    def wrapper(*args):
        print(time.asctime())  # done before addition
        result = func(*args)   # calls the addition function
        ...                    # actions after addition
        return result
return wrapper

@print_timestamp
def addition(a, b):
    """add two arguments a,b and returns the result"""
    return a + b

You can argue that this does not simplify the code in the first place. Using decorators pays off in bigger programs, when they are used often, or imported from different modules.

Most of the time, you would use predefined decorators. Notable places are

  • the functools module
  • classes with @property and @staticmethod
  • the Flask web server
  • pytest

Wrapping Decorators

The wraps decorator copies documentation strings into the decorator function, so that the decorated function looks like the original one. It is useful when writing your own decorators.

import functools

def print_timestamp(func):
    @functools.wraps(func)
    def wrapper(*args):
        print(time.asctime())  # done before addition
        result = func(*args)   # calls the addition function
        ...                    # actions after addition
        return result
return wrapper

@print_timestamp
def addition(a, b):
    """add two arguments a,b and returns the result"""
    return a + b

# check docstring - would not work without @wraps
print(help(addition))

Dr. Kristian Rother

I am a professional Python trainer, developer and author based in Berlin. I believe everybody can learn programming.

Contact me via:
+49 176 3052 4691
krother@academis.eu

Feedback

I want to really thank you! I got a lot of very nice compliments, such as: "Well done, I had a lot of fun". And people were smiling during the talk!!!

Allegra Via, Sapienza University Rome

See also