Python Advanced Programming Builder (Generator) and Coroutine (ii): Coroutine Introduction

Source: Internet
Author: User
Tags generator

Original works, reproduced please indicate the source: point I

Previous article Python Advanced Programming Generator (Generator) and Coroutine (i): Generator, we describe what is Generator, and write a few examples of using Generator function, this section, We'll introduce Python's coroutine, and there will be a small example, and the next article will introduce the advanced usage of coroutine in the form of a code step-by-step.

Coroutine (co-process)

What is Coroutine? What's the difference between coroutine and generator? Let's take a look at the following code:

1 defGrep_co (pattern):2     Print "Lookin for%s"%pattern3      whileTrue:4         #after executing the following sentence, the function hangs, waits for the data to be received, through the Send () function5         #yield Line6Line = (yield )7ifPatterninchLine :8PrintLine

Grep_co is a coroutine, from the point of view of the code, Coroutine and generator The only difference is in line 6th, Coroutine is

Line = (yield)

and generator is:

yield Line

So what's the difference between the two? Don't worry, we'll look down:

In Python2.5 and later versions, yield can be used as an expression, which is the use of the Gerp_co () function. So the question is, what should be the value of line in the Gerp_co () function? Who gave him this value?

The answer is simple: the value of line is the caller of our (Grep_co ()) sent the past. How was it sent? easy! You can use the Send (value) function. Let's take a look at the effect:

1>>>defGrep_co (pattern):2     Print "Looking for%s"%pattern3      whileTrue:4Line = (yield)5         ifPatterninchLine :6             Print Line7 8             9>>> g = Grep_co ("python")Ten>>>g One<generator Object Grep_co at 0x01fa3b98>

As with generator, when calling Gerp_co ("Python"), it does not immediately execute the GREP_CO function, but instead returns an object of the generator type, which will be executed only when the object calls next ():

>>> for Python

After calling the next () function, the function begins execution and executes to line 6th, that is, line = (yield), when it encounters the yield keyword, as with generator, at which point the entire function hangs, since yield does not follow other variables ( In general, the yield statement in Coroutine does not follow the return value, which is discussed later, so no data is returned at this time, simply saving the execution environment and suspending execution.

Since Coroutine and generator meet the yield keyword will hang, is it also the same as generator call the next () function to continue execution? In fact, if you can think of this I would be very happy, stating that you have in earnest look, O (∩_∩) o~. Unfortunately the idea is good, but it is wrong, O (∩_∩) o haha ~, should use the Send (value) function. Then go down, call the above G.next (), the function began to execute, encountered the yield keyword, function suspend execution, and now call G.send ("I love Python") function, the execution result is as follows:

>>> g.send ("hello,i Love python") hello,i love python

As you can see, the Send function has a parameter, which is passed as a line variable. After calling the function of send ("I love Python"), the function of Grep_co () will go down to the last place where it was suspended, that is, in line = (yield) sixth row, send ("I love Python") The parameters of the function are passed to the line variable and then executed down until execution is complete or the yield keyword is hit again. In this example, the value of line is "I love Pyhton", the value of the pattern is "python", if the judge is true, print out line, and then proceed, because it is in an infinite loop, again hit the yield this keyword, hang and pause. So we're going to see the results of the above implementation.

>>> g.send ("life wasshort,please use Python")>>> g.send (" Life was short,please use python" was short,please use Python

We continue to invoke the Send (value) function, which repeats the execution of the above procedure.

Speaking so much, then what is Coroutine? I believe the smart you should have guessed it:

The so-called coroutine is a function that contains the yield keyword, but unlike generator, Coroutine uses the yield keyword in the form of value = (yield) and accepts the caller through send (value) The function sends over the data and then consumes this data (consume the value).

In using Coroutine, it is important to note that all coroutine must be called first. Next () or send (None). The generator must be in a pending state before calling send to pass in a value other than none, otherwise an exception will be thrown. Of course, you can also use. Next () to restore the generator, except at this point the value received by Coroutine is none.

You can call. Close () to close coroutine. After Coroutine is closed, an exception is thrown after the. Nect () or. Send (value) is called again.

>>> g.close ()>>> g.send ("Corotuine has already closed") Traceback (recent):  "<pyshell#16>" in <module >    g.send ("Corotuine has already closed") stopiteration 

. Close () throws a Generatorexit exception, and we can catch and handle the exception in the code, and in general we should handle the exception.

1 defgrep (pattern):2     Print "Looking for%s"%pattern3     Try:4          whileTrue:5Line = (yield)6             ifPatterninchLine :7                 Print Line8     exceptGeneratorexit:9         Print "going away. Goodbye"

Of course, you can also throw a specified exception inside the generator by the throw () function.

>>> G.send ("Life are short,please use Python") Life isshort,please use Python>>> G.throw (RuntimeError,"You ' ar hosed") Traceback (most recent): File"<pyshell#14>", Line 1,inch<module>G.throw (RuntimeError,"You ' ar hosed") File"<pyshell#10>", Line 5,inchgrep Line= (yield) Runtimeerror:you'ar hosed

Well, Coroutine has been introduced almost, we can see Coroutine can be very convenient to suspend and execute, there are many population points and exit points, and ordinary functions generally have only one entry point and exit point.

Generator and coroutine used to resemble each other, but that's all, generator and coroutine are two completely different concepts. Generator generates (returns) data for use in iterations (iterator), while Coroutine is required to send data elsewhere, thereby consuming data (consume value).

The next step is to note the use of Coroutine:

First, be sure not to forget to call the. Next () function before using Coroutine. But this is often easy to forget, so you can use a function decorator.

1 # as a decorator, because it is often easy to forget to call the. Next () function 2 def Coroutine (func): 3     def start (*args,**Kargs):4         cr = Func (*args,**Kargs)5         Cr.next () 6         return CR 7     return Start

Second: It is better not to mix generator and coroutine together, that is Receive_value = (yield return_value) this way to use. Because it can be difficult to understand, and there are some very strange situations. Look at the code first:

1 defCountdown_co (n):2     Print "counting down from", N3      whileN >=0:4NewValue = (yieldN)5         #if NewValue is received, Reset n6         ifNewValue is  notNone:7n =NewValue8         Else:9N-= 1

The code was simple, and the coroutine and generator were used, and the weird things happened. First write a function test_countdown_co ():

1 def Test_countdown_co (): 2     c = Countdown_co (5)3for in       C:4         Print  n5         if 5 = = N:6             c.send (3)

Then call this function at the idle terminal and you can see the result of the function being executed as follows:

>>>from  55210

Now, let's Test the Countdown_co () function by typing the TEST_COUNTDOWN_CO () code directly above the idle terminal:

>>> C = Countdown_co (5) for in C:    print  n      If 5 = = N:        c.send (3)        from  553210

Can see the same code, execution results are not the same, very strange ah! So far I have not thought to understand why. If anyone knows the reason, please tell me O (∩_∩) o Thank you!

All right! This article introduces Coroutine's blog is also written well. The next article will introduce some advanced uses of coroutine in the form of complete code. Please look forward to it. O (∩_∩) o haha ~

Python Advanced Programming Builder (Generator) and Coroutine (ii): Coroutine Introduction

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.