Python Generators, yield and send

03th June 2018

Another little known Python feature that deserves more love. This time we're looking at the send function that lets you input values into your generator as it's running. It works through yield and is awesome!


Let’s say you’re programming a scoring system for the local rounders team. In rounders, a batter can score a half-rounder or a full-rounder. It’s also possible for one batter to score a half-rounder and another to score a full-rounder off the same ball, for example if a batter on base 3 and the batter hitting both make it round. In this scenario we can’t just increment the score by 1 each time.

So let’s make a generator that will increase by 1/2 each time by default, but will also accept other values to increment by.

1
2
3
4
5
6
def score_tally():
    score = 0
    default = 0.5
    while True:
        incr = yield score
        score += incr if incr is not None else default

Line 5 is the special one here, that’s what lets us use the send function, as well as the normal next function. When using send, the value is passed to incr. When using next, yield score will return None. This is why we check for None on line 6, before adding incr, or default if incr is None. We can then use this generator like so:

>>> bonkers_batters = score_tally()
>>> next(bonkers_batters)
0
>>> next(bonkers_batters)
0.5
>>> next(bonkers_batters)
1
>>> next(bonkers_batters)
1.5
>>> bonkers_batters.send(1)
2.5
>>> bonkers_batters.send(1.5)
4
>>> next(bonkers_batters)
4.5

The Python Docs for Yield mention send, and the Python Docs for generator gives the bare-bones description. There’s also an async version, although this one has to be awaited.

Until next time, happy coding.
Paul

Post Tags


All Tags



LIFE IS better when we share.


Comments

JOIN THE conversation: awesome comments.