From simple to deep - so you can understand yield in Python thoroughly
It's hard to say you know something that you haven't used and don't deeply understand, and it's bound to break down when asked by others. Although there is a previous exposure to the concept of generators in python, but just a walk in the park, the two days of a conversation, others asked about generators, a moment of incoherence, dead can not think of something once read, after the sudden thought of yield, but it is too late, can only say that the concept is unclear, so this summary today wisp of python generators and yield keywords.
Before introducing yield it is necessary to explain the iterator and the constructor in Python.
I. Iterator
In Python, for loops can be used for any type of Python, including lists, meta-ancestors, etc. In fact, for loops can be used for any "iterable object", which is actually an iterator. An iterator is an object that implements the iterator protocol, which in Python means that objects with a next method advance to the next result, and at the end of a series of results is, a Stopiteration is raised. Any such object can be iterated over in Python using a for loop or other traversal tool, which internally calls the next method at each iteration and catches StopIteration exceptions to determine when to leave.
One obvious benefit of using iterators is that they only read one piece of data from the object at a time, without causing excessive memory overhead.
II. Generator (constructor)
The generator function is associated with the concept of an iterator protocol in Python. In short, functions that contain a yield statement are compiled specifically as generators. When functions are called, they return a generator object, which supports the iterator interface. The function may have a return statement, but it is used to yield to generate the value.
Unlike normal functions that generate values and then exit, generator functions will automatically hang and suspend their execution and state after generating values, and his local variables will hold state information that will be valid again when the function resumes.
After parsing to get a page of information, we need to process the information a bit, traverse to extract the results and generate a dictionary. The purpose of this is to tidy up the data structure (otherwise, the data is rather messy) and make it easier to store the data later.
Here, I used the generator function, which will return an iterator object with all the information of a page in it every time the function is called, as follows.
This way, when we need to save the information, we can simply iterate through this iterative object again and store the 3D lottery information for each issue one by one in the structure we want, with the following code (I am storing the information in an Excel sheet).
Preservation effects.
Analyze this example
The presence of the keyword yield in the parse_one_page function predicts that this function will only produce one result value at a time, and this function returns a generator (as seen by the output of print(parse_one_page)) that is used to produce successive iterative objects
When creating a generator instance, it is only necessary to call it like a normal function, but this call does not execute the function, which can be seen in the output
See here should be able to understand the abstract concept of generators, if you do not understand can leave a comment, I will give you an answer one by one
Why is it called a generator function?
Because he generates a queue of values over time. A normal function would return a value after execution and exit, but a generator function will automatically hang and then pick up again to continue execution; he will use the yield keyword to shut down the function and return a value to the caller, while retaining enough current state to allow the function to continue execution. Generators and iteration protocols are closely related, and iterable objects have a __next()__ member method that either returns the next item in the iteration or causes an exception to end the iteration.
To support the iterative protocol, functions that have a yield statement are compiled as generators; such functions return a generator object when called, and the returned object supports the iterative interface, i.e., the member method __next()__ continues the execution execution from the break.
To gain a deeper understanding, let me give another example.
The results are as follows.
As the saying goes, it's better to see it ten times than to do it once, so get your hands on this amazing and abstract generator concept; if you have a better way to understand it, feel free to share it in the comments!