Python decorators#
Why we need decorator
It will extend your function behaviors during runtime.
For example, you already have a function say_hi
- function name
say_hi - parameter
nameand typestr - one output
say_hi('Apple') => Hi! Apple
Next we plan to add one introduction to the output, such as Hi! Apple. I'm Bob.
-
Modify your function
If this is only used once in our project, itβs manageable. However, modifying the function signature means that every instance of its use throughout the project must be updated, which is both tedious and time-consuming. -
Use decorator
Function signature is not changed and function behavior is enriched
How to create decorator#
Decorator Function#
Before starting decorator, we have to understand
- original function
- function name
- function parameters and types
- decorator function
- extra parameter
- new features
We have an original function
- function name:
hello- parameters:
name- types:
str
Now we can use these to build decorator function my_dec
Explanation:
line 1- decorator name :
my_dec - decorator parameter :
func(we did not use type hint here)
- it mean
my_decwill decorate functionfunc
- decorator name :
line 2- inner function
wrapper(any function names)
- inner function signature. It MUST be a superset of your original signature
e.g. only 1 parameter
nameathellothe wrapper function should includenameat least it could bewrapper(name),wrapper(name, name1=None),wrapper(name, *args, **kwargs)wrapper(*args, **kwargs)etc.
- inner function
line 3return value
line 4return a function name
wrapper
Now the decorator is working as func = my_dec(func)
- function IN :
func - function OUT:
wrapperand reassignedwrappertofunc
Decorator Class#
it's obviously to understand how to setup decorator's parameters.
built-in python decorator#
Each function in python has metadata
__name____doc__
Either function or class cannot update decorator function metadata.
How to update function metadata
- manually update
class DecoratorClass1: def __init__(self, decorator_param: str): self.decorator_param = decorator_param def __call__(self, func): def wrapper(original_param): """Wrapper Doc""" return func(original_param) + self.decorator_param # Manually update metadata wrapper.__doc__ = func.__doc__ wrapper.__name__ = func.__name__ return wrapper - use python built-in
wrapper