Decorator, iterator and generator, and decorator
Decorator
Learn the functions and basic concepts of the decorator from a simple timing function.
import timedef foo(): time.sleep(2) print("Hello world!")foo()
This is a simple print latency program. to calculate how long it takes to run the program without modifying the source code, you need to use a decorator.
Import timedef timmer (func): def wrapper (): "" Timing function "time_start = time. time () func () time_end = time. time () print ("Run time is % s" % (time_end-time_start) return wrapper @ timmerdef foo (): time. sleep (2) print ("Hello world! ") Foo ()
In this function, simply adding @ timmer directly adds a timing function without changing the original program code. This is really amazing, how does this so-called decorator work?
@ Timmer is actually the syntax for calling the decorator. Before calling, we must follow the principle of defining and then calling. @ timmer is actually equivalent to foo = timmer (foo). The program runs the timmer function, using foo as the func parameter, define the function wrapper and return the address space of wrapper. Running foo () is actually running wrapper, and func () in wrapper is foo (), the time difference before and after running is printed out, which is the timing function we want.
The foo () defined here is a non-parametric function without passing parameters. When we need to pass parameters, we need to add wrapper to the dynamic parameter * args, ** kwargs receives input parameters.
Parameter decorations
def auth(func): def wrapper(*args, **kwargs): username = input("Please input your username:") passwd = input("Please input your password:") if passwd == '123' and username == 'jeff': print("Login successful") func() else: print("login error!") return wrapper@authdef index(): print("Welcome to China")index()
Here is a login decorator. When we need to store the authentication information in the function in multiple ways, and confirm the authentication information before the authentication, then we need to add a Parameter Storage authentication method to the function body, and the modifier also needs to pass parameters. At this time, we change the function
def auth(filetype): def auth2(func): def wrapper(*args,**kwargs): if filetype == "file": username=input("Please input your username:") passwd=input("Please input your password:") if passwd == '123' and username == 'jeff': print("Login successful") func() else: print("login error!") if filetype == 'SQL': print("No SQL") return wrapper return auth2@auth(filetype='file') def index(): print("welcome")index()
@ Auth (filetype = 'file') transmits the filetype parameter to the auth parameter, and runs auth to return the address of au22. the function is equivalent to running index = au22 ), the parameter of the outer filetype is included. au22 (index) returns wrapper, executes wrapper, judges filetype, and then logs in.
In this way, the parameters are passed into the decoration device. This is the parameter decorations.
When a function has multiple decorators,
@ccc@bbb@aaadef func() passfunc=ccc(bbb(aaa(func)))
Iterator
Before learning about the iterator, you must first understand the concept of the iteratable object. In python, you can call the _ iter _ () object, that is, the iteratable object, you can call _ next _ () as an iterator, __next _ () for the iterator value.
When next is beyond the scope of the iterator, the python interpreter will prompt stopiteration. You can use the following methods to solve this problem.
try: passexpect StopIteration: break
Or we can also use the for loop traversal iterator. In fact, the for loop is actually converting the object into an iterator and traversing it again, and the automatic completion will not prompt stopiteration.
Advantages and disadvantages of the iterator:
Advantages:
The iterator can traverse objects without indexes,
The iterator is an inert computing task that generates a value each time next, which saves more memory space.
Disadvantages:
The iterator length cannot be obtained before running, and the list is not flexible.
Values can only be returned. values cannot be reversed.
You can use the built-in function isinstance to determine whether it can be iterated.
from collections import Iterable,Iteratorisinstance(*,iterable)isinstance(*,iterator)
Generator
Yield is a generator in the function body.
A generator is essentially an iterator, so it is also applicable to generators.
The difference between yield and return is that the function ends when return returns the first value (the tuples are also a whole), but yield can return multiple values. In the generator function, the yield function is paused every time it is executed. You need to use next to trigger the next step.
Coroutine Functions
def eater(name): print('%s start to eat food'%name) while True: food=yield print('%s get %s ,to start eat'%(name,food)) print('done')e=eater('xx')next(e)e.send('egg') e.send('food')
Define a coroutine function and assign the yield parameter to food. The next () coroutine function initializes the function and stops running the function at yield, then, use the send method to pass the value to the variable food and execute next () at the same time ().
That is to say, if yield is in the expression form, the next (), send, and next operations must be performed before the execution so that the function can continue to run at the last paused position, however, only send can pass a value to yield before triggering the run.
To sum up yield's functions, 1. it is equivalent to encapsulating the _ iter _ and _ next _ methods into the function. 2. compared with return, yield can return multiple values, 3. the function stops running and is saved through yield.