[Python-ideas] Yield-From: Revamped expansion

Nick Coghlan ncoghlan at gmail.com
Sun Mar 22 00:28:27 CET 2009


Greg Ewing wrote:
> I'm thinking about replacing the expansion with the
> following, which hopefully fixes a couple of concerns
> that were raised recently without breaking anything else.
> 
> Can anyone see any remaining ways in which it doesn't
> match the textual description in the Proposal section?
> 
> (It still isn't *quite* right, because it doesn't
> distinguish between a GeneratorExit explicitly thrown
> in and one resulting from calling close() on the
> delegating generator. I may need to revise the text
> and/or my implementation on that point, because I want
> the inline-expansion interpretation to hold.)
> 
>     _i = iter(EXPR)
>     try:
>         _u = _i.next()
>     except StopIteration, _e:
>         _r = _e.value
>     else:
>         while 1:
>             try:
>                 _v = yield _u
>             except GeneratorExit:
>                 _m = getattr(_i, 'close', None)
>                 if _m is not None:
>                     _m()
>                 raise
>             except BaseException, _e:
>                 _m = getattr(_i, 'throw', None)
>                 if _m is not None:
>                     _u = _m(_e)
>                 else:
>                     raise
>             else:
>                 try:
>                     if _v is None:
>                         _u = _i.next()
>                     else:
>                         _u = _i.send(_v)
>                 except StopIteration, _e:
>                     _r = _e.value
>                     break
>     RESULT = _r
> 

I'd adjust the inner exception handlers to exploit the fact that
SystemExit and GeneratorExit don't inherit from BaseException:

    _i = iter(EXPR)
    try:
        _u = _i.next()
    except StopIteration, _e:
        _r = _e.value
    else:
        while 1:
            try:
                _v = yield _u
            except Exception, _e:
                _m = getattr(_i, 'throw', None)
                if _m is not None:
                    _u = _m(_e)
                else:
                    raise
            except:
                # Covers SystemExit, GeneratorExit and
                # anything else that doesn't inherit
                # from Exception
                _m = getattr(_i, 'close', None)
                if _m is not None:
                    _m()
                raise
            else:
                try:
                    if _v is None:
                        _u = _i.next()
                    else:
                        _u = _i.send(_v)
                except StopIteration, _e:
                    _r = _e.value
                    break
    RESULT = _r

I think Antoine and PJE are right that the PEP needs some more actual
use cases though.

Cheers,
Nick.

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



More information about the Python-ideas mailing list