[Python-ideas] Yield-From: Finalization guarantees

Nick Coghlan ncoghlan at gmail.com
Wed Apr 1 18:05:05 CEST 2009


Jacob Holm wrote:
> def averager():
>    count = 0
>    sum = 0
>    while 1:
>        try:            val = (yield)
>        except GeneratorExit:
>            return sum/count
>        else:
>            sum += val
>            count += 1
> 
> avg = averager()
> avg.next() # start coroutine
> avg.send(1.0)
> avg.send(2.0)
> print avg.close()  # prints 1.5

But that's not how it works, unless you're asking Greg to change the PEP
to allow that. And while it looks cute a single layer deep like that, it
goes wrong as soon as you consider the fact that if you get a
GeneratorReturn exception on close(), you *don't know* if that result
came from the outer iterator.

A better way to write that averager would be:

def averager():
   # Works for Python 2.5+
   count = 0
   sum = 0
   while 1:
       val = (yield)
       if val is None:
           yield sum/count
           break
       sum += val
       count += 1

>>> avg = averager()
>>> avg.next() # start coroutine
>>> avg.send(1.0)
>>> avg.send(2.0)
>>> print avg.send(None)
1.5

Cheers,
Nick.

-- 
Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia
---------------------------------------------------------------



More information about the Python-ideas mailing list