Python: Generator

Source: Internet
Author: User

The builder is an advanced usage in Python, and for some time I struggled to understand the generator until I saw the phrase "theyield statement suspends the state of the generator function, retains enough information so that it can continue from where it left off ," and it dawned on me This is the state in the generator hangs, this sentence reminds me of when I play arm MCU in university often encountered a concept-interrupt, MCU in the event of an interrupt signal, before processing interrupt program must first protect the scene, that is, the system before the execution of the interrupt program, Must save the current processor program status word PSW and the program counter PC, and so on, after the completion of the execution of the program in response to resume the following program. Think about it, personally feel that in the protection of the "scene" this point, the truth of the two is similar (perhaps you do not agree), sometimes a new concept of understanding is stuck in a small knowledge point, I have not understood "generator hangs State" is what thing, but back to the moment I think of the knowledge learned before, Then the analogy, some things will suddenly dawned, but also this "association" let me have a more profound understanding of the generator, use it handy. Now in the work, especially when doing data statistics, encountered a particularly long list, I use the generator, not into can save memory, and code more elegant. The following is about the generator, not the right place to welcome criticism!

A generator is a sequence produced by a certain algorithm, that is, the sequence elements can be calculated according to an algorithm, that is, in the process of the cycle of continuous extrapolation of the subsequent elements, so that you do not have to create a complete sequence, thus saving a lot of space. In Python, this side loop computes the mechanism, called the Generator (Generator).

(i) Generator syntax

Generator expression: pass-through list parsing syntax, just replace the list parsing [] with ()

The list of things that the builder expression can do is basically handled, but the list parsing compares the memory when the sequence that needs to be processed is relatively large.

>>> L = [x * x for x in range]]>>> l[0, 1, 4, 9, N, F, $, $, 81]>>> g = (x * x for X In range (+) >>> G<generator object <genexpr> at 0x104feab40>

L is a list, and G is a generator. If you want to print it out one by one, you can pass generator's next () method. Each time you call next (), the value of the next element is computed, and the Stopiteration error is thrown until the last element is computed and no more elements are added. Here is not too much elaboration, we can try at the terminal, and constantly execute g.next (), while you can use sys.getsizeof () to compare the size of the memory used by L and G, here the list of elements less, see the advantages of the generator, but, for G, push into the formula range (10) Change to Range (+), range (+), g of the memory is not changed, you can try.


Generator function: If the yield keyword appears in the function, then the function is no longer a normal function, but a generator function.

But the generator function can produce an infinite sequence so that the list has no way of handling it at all. The effect of yield is to turn a function into a generator, and the function with yield is no longer a normal function, and the Python interpreter treats it as a generator.

def gensquares (n): For I in range (n): Yield i * * 2 for item in Gensquares (5): Print item

This is a simple example of using a generator to return the square of a natural number.


(ii) Methods of generators

We can use the Dir () function to look at the method of the Generator object, as follows:

[' __class__ ', ' __delattr__ ', ' __doc__ ', ' __format__ ', ' __getattribute__ ', ' __hash__ ', ' __init__ ', ' __iter__ ', ' __name_ ' _ ', ' __new__ ', ' __reduce__ ', ' __reduce_ex__ ', ' __repr__ ', ' __setattr__ ', ' __sizeof__ ', ' __str__ ', ' __subclasshook__ ', ' Close ', ' gi_code ', ' gi_frame ', ' gi_running ', ' Next ', ' send ', ' throw ']


It has the __iter__ () and Next () method, which is not the two basic conditions that the iterator protocol satisfies? (Do not know the iterator protocol, you can see the previous post, click here) that is, the generator is a special iterator.

Close ()

Close the generator function manually, and the subsequent call will return the stopiteration exception directly. See the following simple example:

650) this.width=650; "Src=" Http://s2.51cto.com/wyfs02/M02/8B/62/wKiom1hLkvjBvTB5AABZKcZX7Ls839.png-wh_500x0-wm_3 -wmp_4-s_2117543295.png "title=" Selection _017.png "alt=" Wkiom1hlkvjbvtb5aabzkczx7ls839.png-wh_50 "/>

Send ()

The biggest feature of the generator function is the ability to accept an externally passed-in variable and return it based on the contents of the variable.

This is the most difficult place to understand the generator function and the most important place.

First, let's look at a simple example.

#coding =utf-8def Fun (value=none): print ' begin ' while 1:try:value = (yield value) pri NT "yield" except exception,e:value = eg = Fun (8) print g.next () print "===============" Print G.next () pri NT "===============" Print G.next ()

The results of the operation are as follows:

650) this.width=650; "Src=" Http://s5.51cto.com/wyfs02/M00/8B/5F/wKioL1hLroeTDTlYAAAw15CTFsM013.png-wh_500x0-wm_3 -wmp_4-s_3632871149.png "title=" Selection _019.png "alt=" Wkiol1hlroetdtlyaaaw15ctfsm013.png-wh_50 "/>

The result of the operation shows that, after the generator function is called, its function body is not executed, but until the first call to next () to start execution, and is executed to the yield expression, this time the state hangs , the second call next () Before resuming the pending state then executes, so the first time to execute next () does not print out "yield", to the second call to next (), the first to execute is the print "yield" statement, so also printed out "yield", Until the yield expression is encountered again, then hang, and so on.

One thing to mention here is the yield expression, where next () is called for the first time, and the value = Yield v statement executes only the yield v expression, and the assignment operation is not performed. Only the value of the yield expression is assigned a second time when next () is called, and the default return value of the yield expression is none.

You can refer to this piece of blog http://blog.csdn.net/u014683535/article/details/51757747

There is a difference between the yield 5 in the function and the M = Yield 5.

This may be a bit difficult to understand, for example to verify:

#coding =utf-8class a (object):     def __init__ (self,v):         self._value = v    def fun (Self,value):         print  "Begin"         while  1:            try:                 self._value =  (yield  Value)                 print   "AAA",self._value                 print  "Yield"             except  Exception,e:                 self._value =  Eg = a (8) G = g.fun (print ) "_value  "  ,  g._valueprint  g.next () print  "_value  "  ,G._valueprint  "===============" Print g.next () print  "_value  "  ,G._valueprint  "===============" Print g.next () print  "_ value   " ,g._value

The results of the operation are as follows:

650) this.width=650; "Src=" Http://s5.51cto.com/wyfs02/M02/8B/63/wKiom1hLtdnzXFJVAABIR1AiII8552.png-wh_500x0-wm_3 -wmp_4-s_816926513.png "title=" Selection _020.png "alt=" Wkiom1hltdnzxfjvaabir1aiii8552.png-wh_50 "/>

From the running results, when the first call to next (), the value of G._value does not change, indicating that at this time Self._value = (yield value) did not perform the assignment operation, the second call to next (), the value of G._value changed, is None, Indicates that an assignment operation was performed.


With some of the basics above, understanding the Send () method should be easy, see the following example:

#coding =utf-8def Fun (v): while 1:value = (yield v) if value = = 14:break v = ' Get:%s ' % Valueg = Fun (none) print g.send (none) print g.send () print g.send (14) Print G.send


Execution process:

1. You can start the generator function by G.send (None) or Next (g) and execute to the position where the first yield statement ends.

At this point, the yield statement is executed, but value is not assigned. Note : You can only send (None) when you start the generator function, and you will get an error message if you try to enter a different value. Here, if you remove G.send (None) This sentence, you will get an error.

2. Pass G.send (10), pass in 10 and assign value to value, then calculate the value of V and return to the while head, execution yield v statement has stopped. The "Get:10" is output and then hangs.

3. Through G.send (12), the 2nd step is repeated and the final output is "Got:12"

4. When we G.send (14), the program executes a break and then rolls out the loop, and finally the entire function is executed, so it will be a stopiteration exception.

650) this.width=650; "Src=" Http://s3.51cto.com/wyfs02/M02/8B/63/wKiom1hLwzTTePp4AABPlYMLy1A260.png-wh_500x0-wm_3 -wmp_4-s_3312827546.png "title=" Selection _021.png "alt=" Wkiom1hlwzttepp4aabplymly1a260.png-wh_50 "/>



In fact, send () is the full-featured version of Next (), next () is equivalent to send (None), the previous mention that the yield expression has a "return value", the function of Send () is to control the "return value", so that the return value of the yield expression is its argument.

This sentence to understand, look at the above example, the last printed value is the function of the value of V (that is, the actual argument).

Throw ()

Used to feed an exception to the generator function, which can end a system-defined exception, or a custom exception.

Throw () throws an exception directly and ends the program, or consumes a yield, or directly to the end of the program without the next yield.

#coding =utf-8def Gen (): While True:try:yield ' normal value ' yield ' normal value 2 '            Print (' here ') except Valueerror:print (' We got valueerror here ') except TypeError: Breakg=gen () print next (g) Print G.throw (valueerror) print next (g) Print G.throw (TypeError)

1.print Next (g): The normal value is output and stays before yield ' normal value 2 '.

2. Because G.throw (valueerror) is executed, all subsequent try statements are skipped, that is, yield ' normal value 2 ' will not be executed, then go into the except statement and print out the We got valueerror here. It then enters the while statement part again, consumes a yield, and outputs the normal value. Then the status hangs.

3.print Next (g) executes the yield ' normal value 2 ' statement and stays where it was after the statement was executed.

4.g.throw (TypeError): Will jump out of the try statement so that print (' here ') will not be executed, then execute the break statement, jump out of the while loop, and then reach the end of the program, so run out of the stopiteration exception.

The results of the final operation are as follows:

650) this.width=650; "Src=" Http://s4.51cto.com/wyfs02/M01/8B/63/wKiom1hLxxOjhC2SAABWgtuh7gQ091.png-wh_500x0-wm_3 -wmp_4-s_878858543.png "title=" Selection _022.png "alt=" Wkiom1hlxxojhc2saabwgtuh7gq091.png-wh_50 "/>


The Send () method is more difficult to understand in the main three methods of the generator, but just remember that the function of Send () is to control the yield expression "return value" so that the return value of the yield expression is its argument.

Finally summed up just a few words:

1. The generator is an iterator that can be iterated using for.

2. The first time you execute next (generator), the program suspends after the yield statement is executed, and all parameters and states are saved. Once again, when you execute next (generator), it is executed from the suspended state. The loop ends when the end of the program is encountered or when Stopiteration is encountered.

3. Generator functions are almost the same as regular functions. They are all defined using DEF statements, except that the generator uses the yield statement to return a value, whereas a regular function returns a value using the return statement

4. Parameters can be passed in by Generator.send (ARG), which is the model of the co-process.

5. You can pass an exception by Generator.throw (Exception). The throw statement consumes a yield.

6. You can manually turn the generator off by Generator.close ().

7.next () equivalent to send (None)



Python: Generator

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.