Home > Software design >  Yielding inside coroutine
Yielding inside coroutine

Time:12-13

I have the following code.

def gen():
    while True:        # line 2
        d = yield      # line 3
        yield d        # line 4

x = gen()
next(x)

for i in (3, 4, 5):
    print(x.send(i))   # line 10

When I run this, I get:

3
None
5

rather than:

3
4
5

which is what I would expect. I've already gone through several similar questions (including this one) but I still don't understand what is happening here.

My understanding is as follows: We prime the generator by calling next(x), it starts execution and enters the while loop on line 2. On line 3, we have a yield statement and execution pauses. On line 10, we send the value 3. Execution resumes on line 3, d is set to 3, and we yield back d. On line 10, send returns the yielded value (3). The generator continues execution until we are back to the yield statement on line 3, etc.

Is this incorrect? What am I doing wrong here?

CodePudding user response:

x = yield y does two things:

  1. Return y.
  2. Assign the next sent value to x.

Without y, None gets returned. Without x =, the sent value just gets thrown away.

So what happens here is:

code         effects         comments
---------------------------------------------
d = yield    return None     ok, you ignore it
             d = 3
yield d      return 3        gets printed
             Throw away 4
d = yield    return None     gets printed
             d = 5
yield d      return 5        gets printed

You can fix it like this, always storing and returning every sent value:

def gen():
    d = None  # or `d = yield`, either works, just differently
    while True:
        d = yield d
  • Related