stay Python In the program , Use keywords yield The defined function is called a generator ( Generator ). By using the generator , You can generate a sequence of values for iteration , And the sequence of values is not generated at one time , Instead, use a , Regenerate into one , The biggest advantage is that the program can save a lot of memory .
stay Python In the program , A generator is a function that remembers its position in the body of a function the last time it returned . The second time to the generator function ( Or the first n Time ) Call to jump to the middle of the function , And all the local variables that were last called remain the same . The generator is not only “ remember ” Its data status , also “ remember ” It's in flow control construction ( In command programming , This construction is not just data values ) Position in . In a nutshell , The features of the generator are as follows .
(1) A generator is a function , And the parameters of the function are preserved .
(2) When iterating to the next call , All parameters used are reserved for the first time Under the . in other words , The parameters of all function calls are reserved when they are called for the first time , Not the new one .
stay Python In the program , Use keywords yield Define generator . When you ask the generator for a number , The generator will execute , Until yield When the sentence is , The generator puts yield Pass the parameters to you , After that, the generator will not continue to run . When you ask the generator for the next number , It will run from the last state , Until yield Statement to pass parameters to you , Then stop . So again and again , Until you exit the function .
When in pyton When a function is defined in a program , If you use keywords yield So this function is a generator , Its execution will be very different from other ordinary functions , Function returns an object , Instead of the usual functions retum Sentence like that , We can get the result value . If you want to get value , You also need to call next( ) function , For example, in the following demo code , Every time the iterator is called next( ) function , The generator function will run to yield Location , return yield Value after , And pause here , All the States will be maintained , Until next time next( ) The function exits only when it is called or encounters an abnormal loop .
c = h() #h() Contains yield keyword
# Return value
c.next ()
For example, in the following example code , Demonstrates the use of yield Generator process .
def fib (max): # Define methods fib()
a,b = 1,1 # As a variable a and b The assignment is 1
while a < max: # If a Less than max
yield a # When the program runs to yield This line will not continue to execute
a, b=b,a+b
print (" Changes in the Olympic gold medals table ")
for n in fib(15): # Traverse 15 The value within
print (n)
In the example code above , When the program runs to yield This line will not continue to execute , Instead, it returns a that contains the status of all the parameters of the current function iterator object . The purpose is to be called the second time , All the parameter values of the function that can be accessed are the values of the first access , Instead of reassigning . When the program first calls :
yield a # At this time a,b Values, respectively 1,1, Of course , When the program reaches this line , return
When the program calls the second time , From the front we can see , When called for the first time ,a,b=1,1, Then the second call ( In fact, it is the first time the call returns iterator Object's next( ) Method ), Program jumps to yield Statement place , When executed “a,b= b,a+b” When the sentence is , At this point, the value becomes : a,b=1,(1+1)=>a,b=1,2. Then the program continues while loop , You will encounter again yielda sentence , Just like the first time , Save the state of all parameters of the function , Returns a containing this
Some parameter states iterator object . Then wait for the third time … After execution, it will output :
According to the previous content of this chapter, we can know , stay Python Keywords can be used in programs yield Define a function as a generator . So the generator is also a function , Can generate a sequence of values , For use in iterations . For example, in the following example code , Demonstrated yield Running mechanism of generator :
def shengYield(n): # Define methods shengYield()
while n > 0: # If n Greater than 0 Then start the cycle
print(" To start generating ...:") # Define a generator
yield n
print(" Finish once ...:") # Generating a sequence of decreasing numbers of initial values
n -= 1
if __name__ == '__main__': # When the module is run directly , The following code block will run , Modules are not run when they are imported .
for i in shengYield(4): # Traverse 4 Time
print(" The value obtained by traversal :",i)
print()
sheng_yield = shengYield(3)
print(' The generator object has been instantiated ')
sheng_yield.__next__() # Directly traverse the generator you created
print(" Second call __next__() Method :")
sheng_yield.__next__() # Manually obtain the numerical sequence generated by the generator
In the example code above , Customized a generator of decreasing number sequence , Each time a call is made, a sequence of numbers will be generated, which will decrease continuously from the value provided at the time of the call to the initial value . The generated object can not only be directly for Loop statement traversal , And it can also be traversed manually , In the last two lines of code above, the manual traversal method is used . For the first time for Loop statements directly through the generator you created , For the second time, manually obtain the numerical sequence generated by the generator . After execution, it will output :
The implementation process of the above example shows that , When the generator contains yield When the sentence is , Not only can I use for Direct traversal , You can also call its methods manually __next__() Traversal . stay Python In the program ,yield Statement is the key statement in the generator , The generator does not execute immediately when instantiated , Instead, wait for the method to be called __next__() It starts to run , And when the program is finished yield Statement will maintain the current state and stop running , Wait for the next iteration to resume .
In the execution result of the above example , Output after an empty line “ The generator object has been instantiated ” In front of , The generator object has already been instantiated , But the generator doesn't run ( No output “ To start generating ”). When the method is called manually for the first time __next__() after , Just output “ To start generating ” Tips , This means that the generator is already running , And output “ Second call __next__() Method :” No output before text “ Finish once ” Text , This explanation yield Statement stops running immediately after it runs . On the second invocation of the method __next__() after , Just output “ Finish once …” Text prompt for , This shows that from yield Statement to resume running the generator .
stay Python In the program , adopt yield Statement can make a function a generator , Returns the relevant value , And immediately accept the value passed by the caller . But the reader should pay attention to , When the generator is called for the first time , Cannot be passed to generator None Values other than . Otherwise, it will lead to sales recognition . For example, in the following example code , Demonstrates the specific process of not calling the generator :
def shengYield(n): # Define methods shengYield()
while n>0: # If n Greater than 0 Then start the cycle
rcv = yield n # adopt "rcv" To receive the value from the caller
n -=1 # Generating a sequence of decreasing numbers of initial values
if rcv is not None:
n = rcv
if __name__ == '__main__':# When the module is run directly , The following code block will run , Modules are not run when they are imported .
sheng_yield = shengYield(2) # Start traversal from the default value 2 Start decrement and output
print(sheng_yield.__next__())
print(sheng_yield.__next__())
print(' Pass the baton to another person , Start running again .') # Pass a value to the generator , Reinitialize the generator
print (sheng_yield.send(11)) # When retransmitting a value 11 Give the generator
print (sheng_yield.__next__()) # Get one from 11 Start descending traversal
In the example code above , It implements a process that can receive the value from the caller and reinitialize the generator to generate the value . First, a generator function is defined , among yield Statement for “rev=yield n”, adopt “rcv” To receive the value from the caller . If only one value is provided during the call , From this value, the generated sequence will be decremented . After program running , Start traversal from 2 Start decrement and output , When retransmitting a value 11 To the generator , Will get one from 11 Start descending traversal . After execution, it will output :
stay Python In the program , You can use methods send( ) Reset the generator's build sequence , This is called synergy . Coroutine is a basic method to solve program concurrency , If the general method is adopted to realize production The traditional problem of concurrent and synchronous programming, i.e. the consumer and the consumer , Many complex problems need to be considered . But if you implement a co process through a generator in this way , This problem can be well solved . For example, in the following example code , Demonstrates the process of using a coroutine to reset the generator sequence .
def xie(): # Method xie() Represents the producer model
print(' Other team members are waiting to receive and process tasks ...')
while True: # Each loop simulation sends a task to the consumer model ( generator )
data = (yield)
print(' Mission received : ',data)
def producer () : # Method producer() Represents the consumer model
c = xie() # Call function xie() To handle the task
c.__next__()
for i in range(3): # Traverse 3 A mission
print(' Famous swimmer x Yang sends a task ...',' Mission %d'%i)
c.send(' task number %d'%i) # Send task
if __name__ == '__main__':
producer()
In the example code above , This paper demonstrates the implementation of a simple producer and consumer programming model . By defining two functions xie( ) and producer ( ) Represent consumer and producer models respectively , And the consumer model is actually a generator . In the producer model function, each loop simulation sends a task to the consumer model ( generator ), And the generator can call related functions to process tasks . This is through yield Of the statement “ stop it ” Features to accomplish this task . The program is running , Each send task is done by calling the generator function send( ) Realized , The generator that receives the task will execute the relevant function calls and complete the subtasks . After execution, it will output :