Python provides a simple, yet powerful syntax called ‘decorators’. A decorator is a function or class that wraps (decorates) a function or a method. The ‘decorated’ function or method will replace the original ‘undecorated’ function or method. Because functions are first-class objects in Python, this can be done ‘manually’, but using the @decorator syntax is clearer and thus preferred.
def foo(): # do something def decorator(func): # manipulate func return func foo = decorator(foo) # Manually decorate @decorator def bar(): # Do something # bar() is decorated
This mechanism is useful for separating concerns and avoiding external unrelated logic ‘polluting’ the core logic of the function or method.
A good example of a piece of functionality that is better handled with decoration is memoization or caching: you want to store the results of an expensive function in a table and use them directly instead of recomputing them when they have already been computed. This is clearly not part of the function logic.