pythongeneratorsendyield

Python next and send in same generator


This snippet of python I wrote is not behaving the way I expect, given my understanding of yield. Perhaps someone could enlighten me.

def printvar():
    yield 3
    data = yield
    print(data)
    data = yield
    print(data)

x = printvar()
print(next(x))
x.send(4)
x.send(5)

What I expect:

3
4
5

What I get:

3
5

Can anyone explain this behavior?


Solution

  • There are two issues. One is that by advancing the generator three times, you only advance it up to the last yield, not to the code after that. The other is that send puts its value in as the value of the yield statement where execution was previously suspended, not at the next one. Here is a step-by-step explanation of what happens:

    1. Your first call to next executes the first yield 3.
    2. Your next call to send(4) causes yield 3 to evaluate to 4, but you don't do anything with this in printvar, so the value is discarded. .send(4) also advances the generator to the first data = yield, yielding None.
    3. Your next call to .send(5) causes this first data = yield to set data to 5, and also advances the generator to the last yield, again yielding None.
    4. That's it. You don't advance the generator any further, so execution remains stopped at the last yield, never executing the last print.

    The thing to remember when using send is that it sends the value to the place that already yielded, not to the place where it's going to yield next. See this similar question for more explanation.