In the Flask service, I have defined a decorator that I hope can be used to record some information, and then obtain the information recorded by all decorators by obtaining them. So how do I get all the decorations
My requirement is to record some function information through @xxx in a way similar to Swagger, such as @decorator ('auther','time','effect') I had never understood the difference between a decorator and an annotation before, and just now I suddenly realized that decorators are more about extensions. They will hijack the calls to the decorated functions and then add the logic pointed by the decorator. The above is my understanding of decorators, and I don't know if it is correct. Now I want to obtain all the information recorded by the decorator, is it feasible?
In Python, a decorator is simply a function that takes the decorated function as an argument. The interpreter will pass the decorated function to the decorator and set the return value back to the decorated function.
This is best illustrated with an example.
def my_decorator(function):
print('Decorated function:', function)
return function
@my_decorator
def function(a):
return a + 1
is equivalent to:
def my_decorator(function):
print('Decorated function:', function)
return function
def function(a):
return a + 1
function = my_decorator(function)
The above is the simple usage of a decorator, where arguments aren't needed. However, when you need to pass arguments to your decorator, things get a little messier. Take as an example:
def print_when_decorated(data):
def actual_decorator(function):
print('The actual decorator is called, the data is', data)
return function
return actual_decorator
@print_when_decorated('hello world')
def my_function():
return 12345
In this case, Python will first call your decorator (print_when_decorated
) with the argument 'hello world'
passed to data
. Then, inside the print_when_decorated
function, another function is defined, which is actual_decorator
. Then print_when_decorated
returns it.
So, Python will decorate my_function
with the return value of the print_when_decorated('hello world')
call, which is actual_decorator
. And thus, the code will output The actual decorator is called, the data is hello world
.
So, in your case, you can store the necessary data in an attribute on the function object. For example:
def decorator(author, time, effect):
def actual_decorator(function):
function.__my_decorator_data__ = (author, time, effect)
return function
return actual_decorator
This defines an attribute __my_decorator_data__
on the function, which is simply a Python object. (The attribute name doesn't matter at all; you can name it whatever you'd like as long as it doesn't collide with an existing attribute.) Because Python objects are not like Java objects (for example), where all fields must be defined, you can set attributes on most objects (such as functions) whenever you want.
Then to get the data from the function, just retrieve the attribute set earlier:
# Suppose `function` is decorated with `@decorator('abc', 'def', 'ghi')`
function.__my_decorator_data__ # returns ('abc', 'def', 'ghi')