This article mainly introduces the Python generator definition and simple usage, combined with the example form more detailed analysis of the Python generator concept, principles, usage and related operations considerations, the need for friends can refer to the following
The examples in this article describe Python builder definitions and simple usages. Share to everyone for your reference, as follows:
First, what is the generator
In Python, the list size is bound to be limited due to memory constraints. For example, if we create a list of 100 million elements, Python will first open up enough space in memory to store the list of 100 million elements before allowing the user to use the list, which could lead to the following problems:
1. There is not enough memory space in memory to store this list, which prevents the list from being created
2. Even if the list is created successfully, it will still take a long time, resulting in inefficient programs
3, if the user only want to access a few elements in front of the list, then the vast majority of elements in the following list of space is wasted
In order to solve the above problems effectively, Python introduces a new mechanism of "one side loop, one side computing ", that is, when the user needs to use an object, Python creates the memory space according to the rules designed by the user to create the object for use. Instead of making all the objects available to the user before they are created as a list . This mechanism becomes the generator (generator) in Python.
Ii. Creation of generators
A, generator push-to-type
Similar to a list push, except that the generator infers using () instead of [], and ultimately returns a generator instead of a list
G= ((i+2) **2 for I in range (2,30)) #g是一个生成器print (g) #g为空 containing any element
Operation Result:
<generator Object <genexpr> at 0x0000000002263150>
B, yield key word
Include the yield keyword in a function definition, the function is no longer a normal function, but a generator (generator)
[Note that the]:yield instruction can pause a function and return the result, and a function that uses that instruction will save the execution environment and, if necessary, restore
def fib (max): n,a,b=0,0,1 while N<max: #print (b) yield b a,b=b,a+b n+=1 return ' Done ' F=fib (6) print (f)
Operation Result:
<generator Object fib at 0x0000000002553150>
[Note]: The difference between a normal function and a function that becomes a generator:
The normal function is executed sequentially, and the return or last line function statement is returned. The function that becomes the generator executes every time the __next__ () method is called, encounters a yield statement, and resumes execution from the yield statement that was last returned.
F=FIB (6) print (f) print (f.__next__ ()) print (f.__next__ ()) print (' Pause ') print (f.__next__ ()) print (f.__next__ ())
Operation Result:
<generator Object fib at 0x00000000025631a8>
1
1
Pause for a moment
2
3
Third, generator method (reference: Bole online)
1.close () Method: Manually close the generator function, and subsequent calls will return the stopiteration exception directly
def func (): yield 1 yield 2 yield 3g=func () g.__next__ () G.close () #手动关闭生成器g. __next__ () #关闭后, yield 2 and yield 3 statements will no longer work
Operation Result:
Traceback (most recent):
File "E:\py3Demo\Hello\generatorDemo.py", line 9, <module>
G.__next__ () #关闭后, yield 2 and yield 3 statements will no longer work
Stopiteration
2.__next__ () Method: Returns the next call of the generator
def func (): n=1 for I in range (3): yield n n+=1c=func () a1=c.__next__ () a2=c.__next__ () a3=c.__next__ ( )
[Process explanation]:
For a normal generator, the first __next__ () method calls the equivalent of the start generator, which starts at the first line of the generator function, and then jumps out of the generator function after the first execution of the yield statement (line fourth).
When the second __next__ () method is called, it re-enters the generator function and executes from the next statement (line fifth) of the yield statement until it is rerun to the yield statement, and then jumps out of the generator function again.
Subsequent __next__ () method calls and so on
3.send () Method: Accepts an externally passed-in variable and returns it to the generator function based on the variable content calculation
[Note]:
(1) The Send () method is similar to the __next__ () method, except that the Send () method can be passed to the yield expression value, while the __next__ () method cannot pass a specific value, only pass none to the yield expression, because This can interpret generator.__next__ () as Generator.send (None)
(2) The first call to the generator function, you must use the __next__ () statement or send (None), you cannot use Send to send a value other than None to the generator function, otherwise there will be an error, because there is no yield statement to receive this value
Def gen (): value=0 while True: receive=yield value if receive== ' end ': break value= ' got:%s ' %receiveg=gen () print (g.__next__ ()) #或是print (G.send (None)), which launches the generator print (G.send (' AAA ')) Print (G.send (3)) print ( G.send (' End '))
Operation Result:
0
Got:aaa
Got:3
Traceback (most recent):
File "E:\py3Demo\Hello\generatorDemo.py", line A, in <module>
Print (G.send (' End '))
Stopiteration
[Process explanation]:
A. Start the generator function by G.send (None) or g.__next__ () and execute to the position where the first yield statement ends and suspend the function. The yield statement is executed at this point, but the receive assignment is not assigned, so yield value outputs the initial value of value 0
B.g.send (' AAA ') First string ' AAA ' enters the generator function and assigns a value to receive, then starts executing the function (fifth sentence) from the next sentence of the yield statement, calculates the value and returns to the while header to start a new round of the loop, which stops when executing to the yield value statement, where yield Value outputs ' got:aaa ', then hangs
C.g.send (3) Repeat step B, the final output is ' Got:3 '
D.g.send (' end ') causes the program to break and then jumps out of the loop, so the function executes and the stopiteration exception is obtained.
4.throw () Method: Sends an exception to the generator.
Def gen (): while True: try: yield ' normal value ' #返回中间结果 where yield and return function similar to yield ' normal value2 ' print (' I am here ') except ValueError: print (' We got ValueError ') except Exception: print (' Other errors ') Breakg=gen () print (g.__next__ ()) Print (G.throw (valueerror)) print (g.__next__ ()) Print (G.throw ( TypeError))
Operation Result:
Traceback (most recent):
File "E:\py3Demo\Hello\generatorDemo.py", line +, in <module>
Print (G.throw (TypeError))
Stopiteration
Normal value
We got ValueError
Normal value
Normal value2
Other errors
[Explanation]:
A.print (g.__next__ ()) outputs normal value and stops before yield ' normal value2 '
B. Due to the execution of G.throw (ValueError), the subsequent try statement is skipped, that is, yield ' normal value2 ' will not execute, and then go to the except statement and print out ' We got ValueError '. Then again into the while statement part, consumes a yield, output normal value
C.print (g.__next__ ()) executes the yield ' normal value2 ' statement and stays where it was after the statement was executed
D.g.throw (TypeError) jumps out of the try statement, so print (' I am here ') is not executed and then prints ' other Errors ', and executes the break statement out of the while loop, then arrives at the end of the program, printing the stopiteration exception information
Four, the use of generators
Import timedef Consumer (name): print ('%s ready to eat buns! '%name) while True: Baozi=yield #接收send传的值 and assigns the value to the variable baozi print (' Bun [%s] came, eaten by [%s]! '% (Baozi,name)) def producer (name): c1=consumer (' A ') #把函数变成一个生成器 c2=consumer (' B ') c1.__next__ () # Calling this method will go to yield and temporarily return to c2.__next__ () print (' Start preparing buns! ') for I in range: time.sleep (1) print (' Make a bun, split into two halves ') c1.send (i) c2.send (i) Producer ( ' Tomwenxing ')
Operation Result:
A ready to eat buns!
B ready to eat steamed buns!
Get ready to make buns!
made a bun, divided into two halves of the
Bun [0] came, was [A] eaten! The
Bun [0] came and was [B] eaten!
made a bun, divided into two halves of the
Bun [1] came, was [A] eaten! The
Bun [1] came and was [B] eaten!
made a bun, divided into two halves of the
Bun [2] came, was [A] eaten! The
Bun [2] came and was [B] eaten!
made a bun, divided into two halves of the
Bun [3] came, was [A] eaten! The
Bun [3] came and was [B] eaten!
made a bun, divided into two halves of the
Bun [4] came, was [A] eaten! The
Bun [4] came and was [B] eaten!
made a bun, divided into two halves of the
Bun [5] came, was [A] eaten! The
Bun [5] came and was [B] eaten!
made a bun, divided into two halves of the
Bun [6] came, was [A] eaten! The
Bun [6] came and was [B] eaten!
made a bun, divided into two halves of the
Bun [7] came, was [A] eaten! The
Bun [7] came and was [B] eaten!
made a bun, divided into two halves of the
Bun [8] came, was [A] eaten! The
Bun [8] came and was [B] eaten!
made a bun, divided into two halves of the
Bun [9] came, was [A] eaten! The
Bun [9] came and was [B] eaten!