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.