Catalog
4. Grammatical sugar for ornaments@
8. Class ornaments with parameters
Preface
Recently, when someone asked me what a decoration is, I told him that it was actually a decoration that resembled a girl's hairpin.A girl you like can have many haircards. When she wears different haircards, she has different haircards on top of her head.But the girl you like is the one you like.If you still don't understand it, the ornament is our mobile phone shell. Although you put on the mobile phone shell, it doesn't affect the function of your mobile phone, but your mobile phone should still be able to play for you. Call you, play games, and play games. This collection of Siege Lion Baiyu is for Siege Lion Baiyu's blog.And your phone becomes a phone with a mobile phone shell.
The ornament is one of python's road tigers. If you do or don't do it, it's all there.If you want to learn advanced Python usage, the ornament is a tiger that you Wusong must knock down.
The environment for this article is as follows:
win10,python3.7
1. What is an ornament
Decorator is a small addition to existing modules, which can extend the functions of the original function without modifying the content of the original function or the call of the original function.
The use of decorators conforms to the open and closed principle of object-oriented programming.
The principle of openness and closure is mainly reflected in two aspects:
- Open to extensions means that existing code can be extended to accommodate new requirements or changes.
- Closed to modifications means that once a class is designed, it can work independently of any modifications to the class.
2. Why use ornaments
Before you use the decorator, we need to know that everything in python is an object, that is, everything can be transmitted.
Functions can also be passed as parameters to a function.
This simple example provides a more intuitive way to see how function names are passed directly as parameters
def baiyu(): print("I am Siege Lion Baiyu") def blog(name): print('Get into blog function') name() print('My blog is https://blog.csdn.net/zhh763984017') if __name__ == '__main__': func = baiyu # Here we assign the function name baiyu to the variable func func() # Execute func function print('------------') blog(baiyu) # Pass the function baiyu as an argument to the blog function
The results are as follows:
Next, I want to know how long the baiyu and blog functions take to execute, so I'll modify the code as follows:
import time def baiyu(): t1 = time.time() print("I am Siege Lion Baiyu") time.sleep(2) print("The execution time is:", time.time() - t1) def blog(name): t1 = time.time() print('Get into blog function') name() print('My blog is https://blog.csdn.net/zhh763984017') print("The execution time is:", time.time() - t1) if __name__ == '__main__': func = baiyu # Here we assign the function name baiyu to the variable func func() # Execute func function print('------------') blog(baiyu) # Pass the function baiyu as an argument to the blog function
The above overrides have already fulfilled the functions I need, but when I have another new function [python_blog_list) as follows:
def python_blog_list(): print('''[Python]Crawler battle, zero base initial crawler download pictures (with source code and analysis process) https://blog.csdn.net/zhh763984017/article/details/119063252 ''') print('''[Python]In addition to multithreading and multiprocessing, you also have to work together https://blog.csdn.net/zhh763984017/article/details/118958668 ''') print('''[Python]Crawler speed-up tips, multithreading and multiprocessing (with source code examples) https://blog.csdn.net/zhh763984017/article/details/118773313 ''') print('''[Python]Crawler resolver Xpath,Quick mastery from shallow to deep (with source code examples) https://blog.csdn.net/zhh763984017/article/details/118634945 ''')
You also need to calculate the execution time of the function, which, according to the previous logic, is rewritten as follows:
def python_blog_list(): t1 = time.time() print('''[Python]Crawler battle, zero base initial crawler download pictures (with source code and analysis process) https://blog.csdn.net/zhh763984017/article/details/119063252 ''') print('''[Python]In addition to multithreading and multiprocessing, you also have to work together https://blog.csdn.net/zhh763984017/article/details/118958668 ''') print('''[Python]Crawler speed-up tips, multithreading and multiprocessing (with source code examples) https://blog.csdn.net/zhh763984017/article/details/118773313 ''') print('''[Python]Crawler resolver Xpath,Quick mastery from shallow to deep (with source code examples) https://blog.csdn.net/zhh763984017/article/details/118634945 ''') print("The execution time is:", time.time() - t1)
If you want to write like this, don't you repeat the wheel?Although human nature is a pigeon king and a repeater, being a good C V attack lion (ctrl+c and ctrl+v) is sure to find ways to be lazy.
Decorators, that is, they allow us to expand some functions that the original function does not have.
3. Simple ornaments
Based on the above function execution time requirements, we implemented a simple handwritten decorator.
import time def baiyu(): print("I am Siege Lion Baiyu") time.sleep(2) def count_time(func): def wrapper(): t1 = time.time() func() print("The execution time is:", time.time() - t1) return wrapper if __name__ == '__main__': baiyu = count_time(baiyu) # Because decorator count_The time function object wrapper returned by time (baiyu), which is equivalent to baiyu = wrapper baiyu() # Executing baiyu() is equivalent to executing wrapper()
Count_hereTime is an ornament, the ornament function defines a wrapper function, the func function is passed in as a parameter, the function is to wrap the func and return the wrapper function.The wrapper function body is to implement the contents of the decorator.
Of course, the wrapper function name here is customizable, as long as the function name you define is the same as the function name you return ed
4. Grammatical sugar for ornaments@
If you've seen the code in other python projects, you'll inevitably see the @ symbol, which is the grammatical sugar for the decorator.So the simple decorator above can be achieved by grammatical sugar, which can be omitted
baiyu = count_time(baiyu)
This code calls the baiyu() function directly
In other words, what actually uses the decorator is that the default parameter passed in is the decorated function.
import time def count_time(func): def wrapper(): t1 = time.time() func() print("The execution time is:", time.time() - t1) return wrapper @count_time def baiyu(): print("I am Siege Lion Baiyu") time.sleep(2) if __name__ == '__main__': # baiyu = count_time(baiyu) # Because decorator count_The time function object wrapper returned by time (baiyu), which is equivalent to baiyu = wrapper # baiyu() # Executing baiyu() is equivalent to executing wrapper() baiyu() # With the grammar sugar, you can call the function directly
5. Decorator Hands-on
When our decorated function is parameterized, how do we write the decorator?
Above we have defined a blog function that is parameterized
def blog(name): print('Get into blog function') name() print('My blog is https://blog.csdn.net/zhh763984017')
At this point, our decorator function should be optimized and modified to accept any parameter of the decorator
def count_time(func): def wrapper(*args,**kwargs): t1 = time.time() func(*args,**kwargs) print("The execution time is:", time.time() - t1) return wrapper
Here, the parameters of our wrapper function are *args and **kwargs, indicating that any parameter can be accepted
Then we can call our decorator.
import time def count_time(func): def wrapper(*args, **kwargs): t1 = time.time() func(*args, **kwargs) print("The execution time is:", time.time() - t1) return wrapper @count_time def blog(name): print('Get into blog function') name() print('My blog is https://blog.csdn.net/zhh763984017') if __name__ == '__main__': # baiyu = count_time(baiyu) # Because decorator count_The time function object wrapper returned by time (baiyu), which is equivalent to baiyu = wrapper # baiyu() # Executing baiyu() is equivalent to executing wrapper() # baiyu() # With the grammar sugar, you can call the function directly blog(baiyu)
6. Decorators with parameters
Previously, we know that the decoration function is also a function. Since it is a function, then parameters can be passed. How can we write a decoration with parameters?
Our ornament just has a count, so what should I do if I want to pass in some notes msg information when using it?Let's take a look at the code below
import time def count_time_args(msg=None): def count_time(func): def wrapper(*args, **kwargs): t1 = time.time() func(*args, **kwargs) print(f"[{msg}]The execution time is:", time.time() - t1) return wrapper return count_time @count_time_args(msg="baiyu") def fun_one(): time.sleep(1) @count_time_args(msg="zhh") def fun_two(): time.sleep(1) @count_time_args(msg="mylove") def fun_three(): time.sleep(1) if __name__ == '__main__': fun_one() fun_two() fun_three()
Let's base on the original count_Outside the time function is a layer of count_to receive parametersTime_Args, the parameters received can be called directly in the internal function.The above code executes as follows:
7. Class Decorators
Let's learn how to write the decorator function together. In python, in fact, the same kind of decorator can also achieve the function of decorator, called decorator like.The implementation of the class decorator calls u inside the classCall_uFunction.Class decorators are easier to write than our decorator functions.
When we use a class as an ornament, the workflow is:
- Pass uInit_u()Method Initialization Class
- Pass uCall_u()Method call s the real decorative method
import time class BaiyuDecorator: def __init__(self, func): self.func = func print("Executing Class__init__Method") def __call__(self, *args, **kwargs): print('Get into__call__function') t1 = time.time() self.func(*args, **kwargs) print("The execution time is:", time.time() - t1) @BaiyuDecorator def baiyu(): print("I am Siege Lion Baiyu") time.sleep(2) def python_blog_list(): time.sleep(5) print('''[Python]Crawler battle, zero base initial crawler download pictures (with source code and analysis process) https://blog.csdn.net/zhh763984017/article/details/119063252 ''') print('''[Python]In addition to multithreading and multiprocessing, you also have to work together https://blog.csdn.net/zhh763984017/article/details/118958668 ''') print('''[Python]Crawler speed-up tips, multithreading and multiprocessing (with source code examples) https://blog.csdn.net/zhh763984017/article/details/118773313 ''') print('''[Python]Crawler resolver Xpath,Quick mastery from shallow to deep (with source code examples) https://blog.csdn.net/zhh763984017/article/details/118634945 ''') @BaiyuDecorator def blog(name): print('Get into blog function') name() print('My blog is https://blog.csdn.net/zhh763984017') if __name__ == '__main__': baiyu() print('--------------') blog(python_blog_list)
8. Class ornaments with parameters
When the decorator has parameters, uInit_u()Functions cannot be passed into func (func stands for the function to be decorated), and func is in uCall_uPassed in when the function is call ed.
class BaiyuDecorator: def __init__(self, arg1, arg2): # The parameters inside the init() method are ornament parameters print('Execution Class Decorator Of__init__()Method') self.arg1 = arg1 self.arg2 = arg2 def __call__(self, func): # Because the decorator takes parameters, the location where the incoming function variable is received is here print('Execution Class Decorator Of__call__()Method') def baiyu_warp(*args): # The decorator's function name can be freely named here as long as it is the same as the return ed function name print('implement wrap()') print('Decorator parameters:', self.arg1, self.arg2) print('implement' + func.__name__ + '()') func(*args) print(func.__name__ + '()completion of enforcement') return baiyu_warp @BaiyuDecorator('Hello', 'Baiyu') def example(a1, a2, a3): print('afferent example()Parameters:', a1, a2, a3) if __name__ == '__main__': print('Ready to invoke example()') example('Baiyu', 'Happy', 'Coder') print('Test code execution completed')
I suggest you compare the code here with the decorator code without parameters to gain a better understanding.
9. Order of ornaments
A function can be decorated by multiple decorators, so what is the order in which the decorators are executed?Let's execute the code below to make it clear
def BaiyuDecorator_1(func): def wrapper(*args, **kwargs): func(*args, **kwargs) print('I'm Decorator 1') return wrapper def BaiyuDecorator_2(func): def wrapper(*args, **kwargs): func(*args, **kwargs) print('I'm Decorator 2') return wrapper def BaiyuDecorator_3(func): def wrapper(*args, **kwargs): func(*args, **kwargs) print('I'm Decorator 3') return wrapper @BaiyuDecorator_1 @BaiyuDecorator_2 @BaiyuDecorator_3 def baiyu(): print("I am Siege Lion Baiyu") if __name__ == '__main__': baiyu()
From the output results, the function decorated by the decorator is executed first, then the decorator's content is executed from inside to outside.
The code for our function with three decorators is as follows:
@BaiyuDecorator_1 @BaiyuDecorator_2 @BaiyuDecorator_3 def baiyu(): print("I am Siege Lion Baiyu")
The above code can be seen as follows to understand why it was executed from the inside out
baiyu = BaiyuDecorator_1 (BaiyuDecorator_2 (BaiyuDecorator_3(baiyu)))
summary
This article introduces python's decorators in depth, and shows how to write your own handwritten decorator functions and class decorators through code.
Write after
If you find it useful, take the trouble to support Siege Lion Baiyu one by one, and share this article with more partners.Your simple support, my unlimited creative power