from __future__
from __future__

Reputation: 315

strange behavior of Coroutine

I'm learning about Coroutine but it work strange that I can't understand... Here's the source

@coroutine
def printer():
    tmp=(yield)
    print tmp

def sender(coru):
    coru.send("hello")
    print "I'm sender"

if __name__=="__main__":
    coru=printer()
    sender(coru)
    print "I'm master"

shows

hello

StopItertationError @ coru.send("hello")

while,

@coroutine
def printer():
          while 1:
               tmp=(yield)
               print tmp

def sender(coru):
    coru.send("hello")
    print "I'm sender"

if __name__=="__main__":
    coru=printer()
    sender(coru)
    print "I'm master"

shows

hello

I'm sender

I'm master

correctly.

So I'm wondering

  1. why coroutine always work with the loops and why the first example rise error

  2. I heared about 'yield from' syntax at version 3.3. Is that help to make the first one work?

  3. I know every coroutine function work equivalently unlike the subroutines.

    but then, I think, after the Printer function ends, the program should be terminated without returning to Sender.

    but it does. doesn't it means that sender superior to printer? what is the difference between subroutine and coroutine then.

thanks for reading and I really appreciate if you enlight me:)

Upvotes: 4

Views: 567

Answers (2)

unutbu
unutbu

Reputation: 880269

When a generator (like printer) ends, it raises a StopIteration exception.

When Python executes

coru.send("hello")

it jumps to

tmp = (yield)

and assigns "hello" to tmp. It then executes the next line:

print tmp

and then the generator ends, thus raising the StopIteration exception.

If, on the other hand, you do not allow printer to end (by using a while 1 loop) then the StopIteration exception is never raised. Instead execution (in printer) continues until the next yield expression is reached:

tmp = (yield)

The send method returns the value of that yield expression (in this case, None). At this point, Python has once again returned to the sender function and next executes

print "I'm sender"

The purpose of the yield from syntax is to make it easier to refactor generators (intended to be used with send and throw) into subgenerators. See PEP380 and What's New in Python3.

It doesn't change the StopIteration behavior.

Upvotes: 5

Nicolas Barbey
Nicolas Barbey

Reputation: 6797

This is a very nice introduction to coroutines :

http://www.dabeaz.com/coroutines/

In particular, you can have a look at :

http://www.dabeaz.com/coroutines/grep.py

and (exemple @coroutine implementation) :

http://www.dabeaz.com/coroutines/coroutine.py

Upvotes: 2

Related Questions