[Python-Dev] Extended Function syntax

Guido van Rossum guido@python.org
Mon, 10 Feb 2003 08:13:20 -0500


Note that this was discussed endlessly when generators were first
invented.  IIRC, it appeared impossible to implement this in a
reasonable manner.

> Sorry to reply to myself, just wanted to mention that I found a real
> need for iterators to have an explicit "finally" action.  For my
> program I will have to invent some convoluted way of doing it :-(
> 
> On Mon, Feb 03, 2003 at 05:10:42PM +0100, Armin Rigo wrote:
> > If no first-class thunks are wanted, then maybe the most direct
> > path from today to auto-closing files is to extend the iterator
> > protocol with an optional __leave__() method.  It would be called
> > exactly once when the iterator is considered to be exhausted.  The
> > semantics of 'for' would be modified to always call it at the end
> > of the loop, even when an exception or a return occurs within the
> > loop.
> 
> This seems (to me) natural because in generators you could then put
> a 'yield' inside of a 'try-finally' pair.  The semantics of
> 
>   def g():
>     try:
>       yield 5
>     finally:
>       <so-some-cleanup>
> 
> are quite clear if it is guaranteed that
> 
>   for x in g():
>     ...
> 
> always cause the 'finally' part of the generator to be called at the
> end of the loop.  That's even something that is straightforward to
> implement, given that loops already set up a block stack entry, just
> like try-finally clauses.  It just adds an extra function to the
> iterator protocol (we could even reasonably re-use tp_clear, for
> example).

But since not all generators are used in for-loops, you can't really
make this the for-loop's responsibility.  And the for-loop might break
out and the iterator might be used more later.

The only place where you could possibly do this to cover all cases
would be in the generator's destructor, which isn't guaranteed to be
called at a specific time in Jython.  Not covering all cases seems
worse to me than the current explicit rule that you can't do this.

--Guido van Rossum (home page: http://www.python.org/~guido/)