[Python-ideas] x=(yield from) confusion [was:Yet another alternative name for yield-from]

Nick Coghlan ncoghlan at gmail.com
Mon Apr 6 00:46:25 CEST 2009


Jacob Holm wrote:
> Greg Ewing wrote:
>> Guido van Rossum wrote:
>>> I don't believe that once the generator has raised StopIteration or
>>> ReturnFromGenerator, the return value should be saved somewhere to be
>>> retrieved with an explicit close() call -- I want to be able to free
>>> all resources once the generator frame is dead.
>>
>> I agree with that.
> 
> I don't think it is common to keep the generator object alive long after
> the generator is closed, so I don't see the problem in keeping the value
> so it can be returned by the next close() call.

I don't think close() means to me what it means to you... close() to me
means "I'm done with this, it should have been exhausted already, but
just to make sure all the resources held by the internal frame are
released properly, I'm shutting it down explicitly"

In other words, the *normal* flow for close() should be the "frame has
already terminated, so just return immediately" path, not the "frame
hasn't terminated yet, so throw GeneratorExit in and complain if the
frame doesn't terminate" path.

You're trying to move throwing GeneratorExit into the internal frame
from the exceptional path to the normal path and I don't think that is a
good idea. Far better to attach the return value to StopIteration as in
Greg's original proposal (since Guido no longer appears to be advocating
a separate exception for returning a value, we should be able to just go
back to Greg's original approach) and use a normal next(), send() or
throw() call along with a helper function to catch the StopIteration.

Heck, with that approach, you can even write a context manager to catch
the result for you:

  @contextmanager
  class cr_result(object):
    def __init__(self, cr):
      self.coroutine = cr
      self.result = None
    def __enter__(self):
      return self
    def __exit__(self, et, ev, tb):
      if et is StopIteration:
        self.result = ev.value
        return True # Trap StopIteration
      # Anything else is propagated

  with cr_result(a) as x:
    # Call a.next()/a.send()/a.throw() as you like
  # Use x.result to retrieve the coroutine's value

Cheers,
Nick.

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



More information about the Python-ideas mailing list