Summary: in this tutorial, you’ll learn about Python class decorators. After the tutorial, you’ll know how to define classes as decorators.
Introduction to the Python class decorators #
So far you have learned how to use functions to define decorators.
For example, the following star
function prints out a number of *
characters before and after calling the decorated function:
def star(n):
def decorate(fn):
def wrapper(*args, **kwargs):
print(n*'*')
result = fn(*args, **kwargs)
print(result)
print(n*'*')
return result
return wrapper
return decorate
Code language: Python (python)
The star
is a decorator factory that returns a decorator. It accepts an argument that specifies the number of *
characters to display.
The following illustrates how to use the star
decorator factory:
@star(5)
def add(a, b):
return a + b
add(10, 20)
Code language: Python (python)
Output:
*****
30
*****
The star()
decorator factory takes an argument and returns a callable. The callable takes an argument (fn
) which is a function that will be decorated. Also, the callable can access the argument (n
) passed to the decorator factory.
A class instance can be a callable when it implements the __call__
method. Therefore, you can make the __call__
method as a decorator.
The following example rewrites the star
decorator factory using a class instead:
class Star:
def __init__(self, n):
self.n = n
def __call__(self, fn):
def wrapper(*args, **kwargs):
print(self.n*'*')
result = fn(*args, **kwargs)
print(result)
print(self.n*'*')
return result
return wrapper
Code language: Python (python)
And you can use the Star
class as a decorator like this:
@Star(5)
def add(a, b):
return a + b
Code language: Python (python)
The @Star(5)
returns an instance of the Star
class. That instance is a callable, so you can do something like:
add = Star(5)(add)
Code language: Python (python)
So you can use callable classes to decorate functions.
Put it all together:
from functools import wraps
class Star:
def __init__(self, n):
self.n = n
def __call__(self, fn):
@wraps(fn)
def wrapper(*args, **kwargs):
print(self.n*'*')
result = fn(*args, **kwargs)
print(result)
print(self.n*'*')
return result
return wrapper
@Star(5)
def add(a, b):
return a + b
add(10, 20)
Code language: Python (python)
Summary #
- Use callable classes as decorators by implementing the
__call__
method. - Pass the decorator arguments to the
__init__
method.