[Python-ideas] Yield-From: Finalization guarantees
Ron Adam
rrr at ronadam.com
Fri Apr 3 07:58:40 CEST 2009
Guido van Rossum wrote:
> On Thu, Apr 2, 2009 at 5:35 PM, Ron Adam <rrr at ronadam.com> wrote:
>>
>> Jacob Holm wrote:
>>
>>> That might be the prevailing wisdom concerning GeneratorExit, at least
>>> partly based on the fact that the only way to communicate anything useful
>>> out of a closing generator is to raise another exception. Thinking a bit
>>> about coroutines, it would be nice to use "send" for the normal
>>> communication and "close" to shut it down and getting a final result.
>>> Example:
>>>
>>> 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
>>>
>>>
>>> To do something similar today requires either a custom exception, or the
>>> use of special values to tell the generator to yield the result. I find
>>> this version a lot cleaner.
>> This doesn't seem less cleaner than the above to me.
>>
>> def averager():
>> sum = 0
>> count = 0
>> try:
>> while 1:
>> sum += yield
>> count += 1
>> finally:
>> yield sum / count
>>
>> avg = averager()
>> avg.next()
>> avg.send(1.0)
>> avg.send(2.0)
>> print avg.next() # prints 1.5
>
> But your version isn't clean -- it relies on "sum += yield" raising a
> TypeError when yield returns None (due to .next() being the same as
> .send(None)).
Something I noticed is that function and method calls use TypeError in
cases where the argument count is miss matched. If there was a different
exception for miss matched arguments and .next() sent no arguments, it
could be rewritten in a somewhat cleaner way.
def averager():
sum = 0
count = 0
try:
while 1:
sum += yield
count += 1
except ArgumentCountError:
yield sum / count
avg = averager()
avg.next()
avg.send(1.0)
avg.send(2.0)
print avg.next() # prints 1.5
This seems to me that a different exception for miss-matched arguments
might be useful in a more general way.
> That's not to say I like Jacob's version that much, but I now
> understand his use case. I note that Dave Beazley works around this
> carefully in his tutorial (dabeaz.com/coroutines/) by using examples
> that produce output on stdout -- and much later, in his multitasking
> schedule example, his trampoline actually interprets yielding a value
> that is neither a SystemCall instance nor a generator as a return from
> a generator. (This is similar to the abuse that your example is giving
> yield, actually.) I'll have to ponder this more.
Yes, generators seem very limiting to me. Generators with more complex
input and output requirements are bound to have added complexities to
offset the limits of a single sequential i/o channel.
> __________
> PS. Somehow the headers in your email made my reply add this:
>
> Python-Ideas <public-python-ideas-+ZN9ApsXKcEdnm+yROfE0A at ciao.gmane.org>,
> Nick Coghlan <public-ncoghlan-Re5JQEeQqe8AvxtiuMwx3w at ciao.gmane.org>
>
> Whoever did that, and whatever they did to cause it, please don't do it again.
I'll manually remove the extra email address's until I (or someone else)
can explain why they do that. I hope that's enough for now.
I read several python groups though gmane using Thunderbird on Ubuntu,
Python-ideas is the only one the email address's are changed like that. (?)
Ron
More information about the Python-ideas
mailing list