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 decorateCode 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:
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
@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 wrapperCode language: Python (python)And you can use the Star class as a decorator like this:
@Star(5)
def add(a, b):
return a + bCode 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)Output:
*****
30
*****Code language: plaintext (plaintext)Summary #
- Use callable classes as decorators by implementing the
__call__method. - Pass the decorator arguments to the
__init__method.