When developing with Python, I think that there are many cases where you want to put common processing before and after a function. In that case, the decorator (the one that annotates the line above the function) is often used. In this article, I'll look at the basics of using decorators, and later on the types of decorators that allow you to pass variables.
The simplest decorator is implemented as follows:
def decorator(func):
def decorated(*args, **kwargs):
print('Decorated start')
func(*args, **kwargs)
print('Decorated end')
return decorated
To actually use this decorator, do the following:
@decorator
def sample(name):
print('{}Worked.'.format(name))
When this decorated sample function is executed, it will be printed as follows. You can see that the processing is inserted before and after the sample function as expected.
Decorated start
sample worked.
Decorated end
The reason why it works like this is that @ is syntactic sugar. This is because it is actually equivalent to the following code.
def sample(name):
print('{}Worked.'.format(name))
# @Equivalent to decorator
sample = decorator(sample)
It's relatively easy to understand so far, but I think there are many cases where you get stuck when trying to understand the type of decorator that allows you to pass variables.
def annotation(param):
print('annotation start')
def decorator(func):
print('Start decorator')
print('param:{}'.format(param))
def decorated(*args, **kwargs):
print('Decorated start')
print('param:{}'.format(param))
func(*args, **kwargs)
print('Decorated end')
print('Decorator finished')
return decorated
print('annotation end')
return decorator
Considering the movement of syntactic sugar (@) earlier, shouldn't the argument of the top-level function (annotation) have to be a function? It's easy to think, but the code below actually works fine.
print('Define annotated function')
@annotation(param=999)
def sample(name):
print('{}Worked.'.format(name))
print('Execute annotated function')
sample('sample')
The print output is shown below
Define annotated function
annotation start
annotation end
Start decorator
param:999
Decorator finished
Execute annotated function
Decorated start
param:999
sample worked.
Decorated end
Looking at the print output above, from among the decorator functions that are called after the annotation function ends. You can refer to param which is the argument of annotation function. The reason for this behavior is that the variables that the function can refer to are determined when the function is defined, so the decorator function defined in the annotation function can refer to the param that is the argument of the annotation function. Because.
Also, considering the contents of the print output, the syntax sugar (@) of the type of decorator that can pass variables is considered to be equivalent to the following.
def sample(name):
print('{}Worked.'.format(name))
# @annotation(param=999)Equivalent to
sample = annotation(param=999)(sample)
Recommended Posts