[Python-Dev] Re: anonymous blocks

Neil Schemenauer nas at arctrix.com
Thu Apr 28 02:48:52 CEST 2005


On Wed, Apr 27, 2005 at 03:58:14PM -0700, Guido van Rossum wrote:
> Time to update the PEP; I'm pretty much settled on these semantics
> now...

[I'm trying to do a bit of Guido channeling here.  I fear I may not
be entirely successful.]

The the __error__ method seems to simplify things a lot.  The
purpose of the __error__ method is to notify the iterator that the
loop has been exited in some unusual way (i.e. not via a
StopIteration raised by the iterator itself).

The translation of a block-statement could become:

        itr = EXPR1
        arg = None
        while True:
            try:
                VAR1 = next(itr, arg)
            except StopIteration:
                break
            try:
                arg = None
                BLOCK1
            except Exception, exc:
                err = getattr(itr, '__error__', None)
                if err is None:
                    raise exc
                err(exc)
        

The translation of "continue EXPR2" would become:

        arg = EXPR2
        continue

The translation of "break" inside a block-statement would
become:

        err = getattr(itr, '__error__', None)
        if err is not None:
            err(StopIteration())
        break

The translation of "return EXPR3" inside a block-statement would
become:

        err = getattr(itr, '__error__', None)
        if err is not None:
            err(StopIteration())
        return EXPR3

For generators, calling __error__ with a StopIteration instance
would execute any 'finally' block.  Any other argument to __error__
would get re-raised by the generator instance.

You could then write:

    def opened(filename):
        fp = open(filename)
        try:
            yield fp
        finally:
            fp.close()

and use it like this:

    block opened(filename) as fp:
        ....

The main difference between 'for' and 'block' is that more iteration
may happen after breaking or returning out of a 'for' loop.  An
iterator used in a block statement is always used up before the
block is exited.

Maybe __error__ should be called __break__ instead.  StopIteration
is not really an error.  If it is called something like __break__,
does it really need to accept an argument?  Of hand I can't think of
what an iterator might do with an exception.

  Neil


More information about the Python-Dev mailing list