In the previous articles of Python decorator series we learnt to create a simple function based decorator, how it works under the hood and how to fix the doc strings.
In this article, we will learn to create a class based decorator and use it to decorate functions.
class HelloDecorator:
"""Simple class decorator"""
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
"""Simple class call method"""
print(f'Calling {self.func.__name__}')
result = self.func(*args, **kwargs)
return result
@HelloDecorator
def add(a, b):
"""Simple function that returns sum of two numbers"""
return a + b
if __name__ == '__main__':
output1 = add(2, 2)
print('Result:: ', output1)
Calling add
Result:: 4
OK, We got the decorator working. Lets look at the help and name and doc attributes,
help(add) # --> prints class definition
print(add.__doc__) # --> prints Simple class decorator
print(add.__name__) # --> Raises AttributeError
Let's try to fix the doc strings,
use funct_tools.partial
to define get magic method and then funct_tools.update_wrapper
to let python know the wrapped function.
from functools import update_wrapper, partial
class HelloDecorator:
"""Simple class decorator"""
def __init__(self, func):
self.func = func
# fixes __name__ and __doc__ attributes
update_wrapper(self, func)
def __get__(self, obj):
"""Fixes help description"""
return partial(self, obj)
def __call__(self, *args, **kwargs):
"""Simple class call method"""
print(f'Calling {self.func.__name__}')
result = self.func(*args, **kwargs)
return result
now lets check the docs,
help(add) # --> prints
"""
add(a, b)
Simple function that returns sum of two numbers
"""
print(add.__doc__) # --> prints "add"
print(add.__name__) # --> prints "Simple function that returns sum of two numbers"
Conclusion, while some may class based decorators prefer, I personally do not prefer class based decorator because of the extra boilerplate code to fix the doc strings.
In the next article, we will implement various kinds decorator recipes. Stay tuned for upcoming articles. Connect with me on twitter to get my future articles.