In the previous article Python decorators 101 we learnt, how to create a simple function based decorator and how it works under the hood. In this article, we will improve the traceability and the readability of the decorator function.
Let's add some docstrings to our code. A docstring is a string literal that is written as the first statement in a module, function, class, or method definition. It becomes the doc special attribute of that object. docstring acts a a built-in documentation.
def hello_decorator(func): """Simple decorator function""" def wrapper(*args, **kwargs): """Simple decorator wrapper function""" result = func(*args, **kwargs) return result return wrapper @hello_decorator def add(a, b): """Simple function that returns sum of two numbers""" return a + b @hello_decorator def multiply(a, b): """Simple function that returns multiplication of two numbers""" return a * b if __name__ == '__main__': help(add) print(add.__name__) print(add.__doc__)
Output
Help on function wrapper in module __main__: wrapper(*args, **kwargs) Simple decorator wrapper function wrapper Simple decorator wrapper function
As you notice that, help and doc string of add function returns the doc string from the decorator wrapper function. This is not good for readability and IDEs will show wrong definition and signature of the decorated function. we don't want this to happen. Lets see how we can fix this,
Fix decorated function docs using functools
from functools import wraps def hello_decorator(func): """Simple decorator function""" @wraps(func) def wrapper(*args, **kwargs): """Simple decorator wrapper function""" result = func(*args, **kwargs) return result return wrapper @hello_decorator def add(a, b): """Simple function that returns sum of two numbers""" return a + b @hello_decorator def multiply(a, b): """Simple function that returns multiplication of two numbers""" return a * b if __name__ == '__main__': help(add) print(add.__name__) print(add.__doc__) output1 = add(2, 2) print('Result:: ', output1) print("=" * 25) help(multiply) print(multiply.__name__) print(multiply.__doc__) output2 = multiply(4, 2) print('Result:: ', output2)
@wraps
function tracks both original function and decorator function and fixes the doc string properly.
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.
Top comments (0)