Python Decorators 102
Now that you know your way around decorators, you're starting to have more complex use cases and you want to figure out how to pass a parameter to your decorator.
Using our @metadata
example from Python Decorators 101, we add some extra nesting like this:
import typing
from functools import wraps
def metadata(custom_parameter: str):
def decorate(func: typing.Callable) -> typing.Callable:
@wraps(wrapped=func)
def wrapper(*args, **kwargs):
metadata_ = {
"function_name": func.__name__,
"docstring": func.__doc__,
"custom_parameter": custom_parameter
}
print(metadata_)
return func(*args, **kwargs)
return wrapper
return decorate
Let's decorate a simple function with this new version of @metadata
:
import typing
from functools import wraps, reduce
from operator import add
def metadata(...
...
...
...
return decorate
@metadata(custom_parameter="Lovely jobly")
def add_all(*integers) -> int:
""" I am a docstring """
return reduce(add, integers)
As usual, let's go into the REPL and press play on that thing:
# python -i decorator.py
>>> add_all(1,2,3)
{'function_name': 'add_all', 'docstring': ' I am a doctring ', 'custom_parameter': 'Lovely jobly'}
6
>>>
See? Your metadata include the decorator parameter value and the result of adding 1 + 2 + 3. It's like magic.
それは 魔法の
Oh, and did you know you can decorate a class too?
@metadata(custom_parameter="I am custom")
class DecorateMe:
""" I am the class """
def print_one(self) -> str:
print("one")
Let's go into the REPL and...
# python -i decorator.py
>>> decorate_me = DecorateMe()
{'function_name': 'DecorateMe', 'docstring': ' I am the class ', 'custom_parameter': 'I am custom'}
You now can do something when the class is instantiated. There are also other ways to do this with inheritance etc but that's another story for another day.