Python generator summary, python generator Summary
Generator concept:
The generator does not save the results in a series, but stores the results in the generator state. A value is returned each time the iteration is performed until the StopIteration exception ends.
A generator is a function that remembers the position in the function body during the last return. The second (or NTH) Call to the generator function jumps to the center of the function, while all local variables in the last call remain unchanged.
The generator not only "remembers" its data status, but also "remembers" its position in the flow control Constructor (in imperative programming, this constructor is not just a data value.
Generator features:
The generator is a function and its parameters are retained.
During iteration to the next call, all the parameters used are reserved for the first time, that is, they are retained when all function call parameters are called for the first time, rather than newly created
Generator syntax
Generator expression: the list parsing syntax, except that the List parsing [] is changed ()
The list parsing of tasks that the generator expression can do can basically be processed. However, when the sequence to be processed is large, the list Parsing is charged for memory.
Generator function: If the yield keyword appears in the function, the function is no longer a common function, but a generator function.
In Python, yield is such a generator.
Yield generator running mechanism:
When you ask the generator for a number, the generator will execute until the yield statement appears. The generator will give you the yield parameter, and then the generator will not continue to run. When you ask him for the next number, he will go from the last status. Run until the yield statement is displayed. Give the parameter to you and then stop. Until the function is exited.
Yield usage:
In Python, When you define a function and use the yield keyword, this function is a generator and its execution will be different from other common functions, the function returns an object instead of the return statement that you normally use to obtain the result value. If you want to obtain the value, you must call the next () function.
The following uses Fibonacci as an example:
#coding:utf8def fib(max): #10 n, a, b = 0, 0, 1 while n < max: #n<10 #print(b) yield b a, b = b, a + b n += 1 return f = fib(10)for i in f: print f
As described in the preceding running mechanism, we can know that the execution will not continue when the program runs to yield. ReturnsContains all parameters of the current functionStatus iteratorObject. The purpose isWhen the second call is called, all the parameter values that can access the function are the values of the first access, rather than re-assigning values.
When the program is called for the first time:
Def fib (max): #10 n, a, B = 0, 0, 1 while n <max: # n <10 # print (B) yield B #, the values of B are 0, 1 respectively. Of course, when the program is executed, a, B = B, a + B is returned.
The second call of the program:
As we can see from the previous figure, when a, B = 0, 0 is called for the first time, then we call the next () method of the iterator object returned for the first time ), the program jumps to the yield statement,
Execute the statements a, B = B, a + B, and the value changes to: a, B = 0, (0 + 1) => a, B = 0, 1
The program continues the while loop. Of course, when the yield a statement is run again, it is also like the first time, saving the status of all the parameters of the function and returning an iterator object containing the status of these parameters.
Wait for the third call ....
Through the above analysis, the detailed operation process of yield can be displayed one by one!
By using the generator syntax, you can avoid the tedious code of writing the iterator class. For example, the above example is implemented using the iteration class. The Code is as follows:
#coding:UTF8class Fib: def __init__(self, max): self.max = max print self.max def __iter__(self): self.a = 0 self.b = 1 self.n = 0 return self def next(self): fib = self.n if fib >= self.max: raise StopIteration self.a, self.b = self.b, self.a + self.b self.n += 1 return self.a f = Fib(10)for i in f: print i
Yield and return
In a generator, if there is no return, the StopIteration is returned when the function is executed by default;
If return is encountered, if return is executed, the StopIteration is directly thrown to terminate the iteration.
If a value is returned after return, an error is reported directly,The generator cannot use return to return values.
Methods supported by the generator (I feel pretty good when using other people's examples)
close(...) | close() -> raise GeneratorExit inside generator. | | next(...) | x.next() -> the next value, or raise StopIteration | | send(...) | send(arg) -> send 'arg' into generator, | return next yielded value or raise StopIteration. | | throw(...) | throw(typ[,val[,tb]]) -> raise exception in generator, | return next yielded value or raise StopIteration.
Close ()
Manually close the generator function. The StopIteration exception will be returned directly in subsequent calls.
#coding:UTF8def fib(): yield 1 yield 2 yield 3f = fib()print f.next()f.close()print f.next()
Send ()
The biggest feature of a generator function is that it can accept a variable passed in from outside and return the result based on the variable content.
This is the most difficult and important part of generator functions,
def gen(): value=0 while True: receive=yield value if receive=='e': break value = 'got: %s' % receive g=gen()print(g.send(None)) print(g.send('aaa'))print(g.send(3))print(g.send('e'))
Execution Process:
The final execution result is as follows:
0got: aaagot: 3Traceback (most recent call last): File "1.py", line 15, in <module> print(g.send('e'))StopIteration
Throw ()
It is used to send an exception to the generator function to end system-defined exceptions or custom exceptions.
Throw () directly runs the exception and ends the program, or consumes a yield, or directly ends at the end of the program without the next yield.
def gen(): while True: try: yield 'normal value' yield 'normal value 2' print('here') except ValueError: print('we got ValueError here') except TypeError: break g=gen()print(next(g))print(g.throw(ValueError))print(next(g))print(g.throw(TypeError))
Execution Process: