This note records your understanding of Python's generator functions and yield expressions.
1. Generator Functions
The generator functions syntax supported by Python allows us to define a function that behaves like a iterator, which can be used in situations where a loop call is required. Compared to the normal function, generator functions only has 1 yield expressions in the function definition, except that there is nothing special about it.
When the generator function is created, the Python interpreter automatically implements the iteration protocol for it (__ITER__ and next methods are implemented, see the Python official documentation iterator Types section) to support the use of iterations where they need to be iterated.
When a normal function is called, the called function is usually executed from line 1th of the function body and exits when a return or throw exception is encountered, and its internal variables are destroyed as well. When generator functions is called, it returns a generator object, which, when called, yields a value each time,rather than return a value(The resulting behavior, which is different from the normal function, is explained in detail when the yield expression is introduced in the next section).
The generator functions has 2 typical features:
1) lazy evaluation, so save memory, see this document improved performance section of the description
2) has iterator behavior characteristics, so it can be used in the For loop
For example, in python2.x, if the for loop has a very large number of loops, in order to save memory, we usually write the following code:
For IDX in xrange (0, 100000000):
Do something
The xrange () function here returns a Xrange object (and range () returns a list object), conceptually, the Xrange object is a generator objects, because generator of the above 2 properties, xrange Object can be used for a for loop, and it consumes very little memory regardless of the number of loops (because it does not generate a list of n elements at a time)
It is important to note that:Generator function provides the expected performance benefit only if it is not necessary to generate the same set of data frequently (most applications are such cases), otherwise its advantages can be turned into a disadvantage.
Through the following scenario, it is believed that it can help us to understand this phrase easily.
Assuming the process of generating 1 integers for a python process is time consuming, here's a way to call sum and product:
>>> s = SUM (xrange (1000000)) >>> p = Product (xrange (1000000))
Another way to achieve this:
>>> nums = List (xrange (1000000)) >>> s = SUM (nums) >>> p = Product (nums)
Obviously, the 1th way to call sum and product is to generate a large collection of integers 1 times, and the 2nd will only be generated 1 times and stored in memory for subsequent use. In our hypothetical scenario, the 2nd approach is more time-saving (typical space-time). However, if machine memory is limited enough to hold a large collection, only the 1th implementation (the tradeoff of time-to-space) can be used, even if its performance is lossy.
in addition to supporting generator functions, Python also supports generator expressions syntax. For a detailed description of the GENERATOR, it is strongly recommended to peruse Python -GENERATOR FUNCTIONS and expressions this article.
2. Yield expression
from the official website document, theyield expression can only be used in the definition of generator function, that is, as long as there is a yield expression in a function definition, the function becomes the generator function, but no longer a normal function.
We can understand the behavior of the yield expression from the literal meaning of "yield": when the program runs to the expression, it temporarily "discards" the right to continue down execution, the control is returned to its caller and the yield expression "produces" The value is also returned to caller, in addition, the function executes the yield expression after the context (including the local scope and local of the function at that moment) Variables and other information) will be saved for subsequent resumption of execution on-site (very similar to the process of CPU processing of interrupt signals).
of course, the idea of only literally inferring yield expression behavior is not rigorous, so the explanation is just to aid understanding. Here's the Python-A more rigorous explanation of the behavior of GENERATOR FUNCTIONS and yield expressions in the GENERATOR FUNCTIONS and expressions article:
Normal functions return a value and then exit. But generator functions automatically suspend and resume their execution. Because of that, they is often a useful alternative to both computing an entire series of values up front and manually sa Ving Tsun and restoring state in classes. Because the state so generator functions retain when they is suspended includes their local scope, their local variable s retain information and make it available when the functions is resumed.
The primary difference between generator and normal functions are that a generator yields a value, rather than returns A value. The yield suspends the function and sends a value back to the caller while retains enough state to enable the function Imm Ediately after the last yield run. This allows the generator function to produce a series of values over time rather than computing them all at once and send ing them back in a list.
to better understand the above paragraph, you can analyze the following code:
The above code defines a generator function called Create_counter with Def to implement the counter functionality.
Object C is a generator object created by Create_counter, which invokes the __next__ method of its parameter C when the Python built-in function next () is called.
remark:The introduction of the 1th section shows that the Python interpreter automatically generates code that supports __next__ when it creates a generator object.
The 1th time you call next (), the C object executes yield N, whose behavior is that the function body is suspended and N is returned to the caller, so you can see that the output of the 1th call to next () does not contain the string "Increment n". In fact, when the function body hangs and returns, its execution context is recorded, but this step cannot be explicitly felt.
On the 2nd call to Next (), the Generator function resumes execution environment (the value of n in this case) after the last suspend, so the "increment n" string is first output, and then n+1, because of the presence of the while loop, So the program executes to yield N, and it hangs and returns, so the terminal output 3
When the nth call to Next (), the function behaves exactly the same as the 2nd invocation, which is not mentioned here.
After really understanding the output of the above code, I believe we will also really understand the yield expression and generator function syntax behavior.
In addition, Improve Your Python: ' yield ' and generators explained the last part of this article makes a very concise and accurate summary of generator and yield expressions, excerpt from the following:
1) Generators is used to generate a series of values
2) Yield is like the return of generator functions
3) The only other thing yield does are save the "state" of a generator function
4) A generator is just a special type of iterator
5) Like iterators, we can get the next value from a generator using next ()
6) for gets the values by calling next () implicitly
I believe that with the introduction of this note, these points are easy to understand.
The following is a section of the use of yield syntax to generate Peibona sequence code, is not very pythonic it? ^_^
#!/bin/env pythondef fib (threshold): A, b = 0, 1 while a < threshold: yield a , B = B, A + B def main ( ): For N in fib: print nif ' __main__ ' = = __name__: main ()
Resources
1. Python Docs:yield Expressions
2. Python-generator FUNCTIONS and EXPRESSIONS
3. Improve Your Python: ' yield ' and generators explained
4. Python PEP 255--Simple generators
5. Python PEP 342--coroutines via enhanced generators
========================= EOF =============================
Python notes how to understand generator functions and yield expressions in Python