Application scenario:
1, Authorization
Decorators can help to check if someone is authorized to use an endpoint of a web application. They are widely used in the Flask and Django web frameworks. Here is an example of using decorator based authorization:
from functools import wraps # The latest python reference is import functools def requires_auth(f): # f is the function we need to decorate. At first glance, it is a decorator without parameters @wraps(f) # New python @ functools.wraps(f) def decorated(*args, **kwargs): auth = request.authorization if not auth or not check_auth(auth.username, auth.password): authenticate() return f(*args, **kwargs) return decorated # The decorator needs to be configured to run. Here is the code interception display application
2. Logging
Log is another highlight of decorator application. Here's an example:
''' //No one answers the questions? Xiaobian created a Python learning exchange QQ group: 579817333 //Looking for like-minded small partners, mutual help, there are good video learning tutorials and PDF ebooks in the group! ''' from functools import wraps def logit(func): @wraps(func) def with_logging(*args, **kwargs): print(func.__name__ + " was called") return func(*args, **kwargs) return with_logging @logit def addition_func(x): """Do some math.""" return x + x result = addition_func(4)
I'm sure you're already thinking about another clever use of decorators.
3. Decorator with parameters
Decorators with parameters are typical closure functions
4. Embed decorator in function
Let's go back to the log example and create a wrapper function that allows us to specify a log file for output
''' //No one answers the questions? Xiaobian created a Python learning exchange QQ group: 579817333 //Looking for like-minded small partners, mutual help, there are good video learning tutorials and PDF ebooks in the group! ''' from functools import wraps def logit(logfile='out.log'): def logging_decorator(func): @wraps(func) def wrapped_function(*args, **kwargs): log_string = func.__name__ + " was called" print(log_string) # Open logfile and write content with open(logfile, 'a') as opened_file: # Now type the log to the specified logfile opened_file.write(log_string + '\n') return func(*args, **kwargs) return wrapped_function return logging_decorator @logit() def myfunc1(): pass myfunc1() # Output: myfunc1 was called # Now a file called out.log appears, which contains the above string @logit(logfile='func2.log') def myfunc2(): pass myfunc2() # Output: myfunc2 was called # Now a file called func2.log appears, which contains the above string
5. Ornaments
Now we have logit decorators that can be used in formal environments, but when some parts of our application are still fragile, exceptions may be something that needs more urgent attention. For example, sometimes you just want to log to a file. Sometimes you want to send an email with a log and a record. This is a scenario using inheritance, but so far we've only seen the functions used to build the decorator.
Fortunately, classes can also be used to build decorators. Let's rebuild logit as a class instead of a function.