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.

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.