[Python-Dev] PEP 342 suggestion: start(), __call__() and unwind_call() methods

Guido van Rossum guido at python.org
Sun Oct 9 03:25:39 CEST 2005


> Guido van Rossum wrote:
> > Before we do this I'd like to see you show some programming examples
> > that show how this would be used. I'm having a hard time understanding
> > where you would need this but I realize I haven't used this paradigm
> > enough to have a good feel for it, so I'm open for examples.

On 10/8/05, Nick Coghlan <ncoghlan at gmail.com> wrote:
> It would be handy when the generators are being used as true pseudothreads
> with a scheduler like the one I posted earlier in this discussion. It allows
> these pseudothreads to "call" each other by yielding the call as a lambda or
> partial function application that produces a zero-argument callable. The
> called pseudothread can then yield as many times as it wants (either making
> its own calls, or just being a well-behaved member of a cooperatively MT
> environment), and then finally returning the value that the original caller
> requested.
>
> Using 'return' for this is actually a nice idea, and if we ever do make it
> legal to use 'return' in generators, these are the semantics it should have.
>
> However, I'm not sure its something we should be adding *right now* as part of
> PEP 342 - writing "raise StopIteration" and "raise StopIteration(result)", and
> saying that a generator includes an implied "raise StopIteration" after its
> last line of code really isn't that difficult to understand, and is completely
> explicit about what is going on.
>
> My basic concern is that I think replacing "raise StopIteration" with "return"
> and "raise StopIteration(EXPR)" with "return EXPR" would actually make such
> code easier to write at the expense of making it harder to *read*, because the
> fact that an exception is being raised is obscured. Consider the following two
> code snippets:
>
>    def function():
>       try:
>          return
>       except StopIteration:
>          print "We never get here."
>
>    def generator():
>       yield
>       try:
>          return
>       except StopIteration:
>          print "But we would get here!"

Right.  Plus, Piet also remarked that the value is silently ignored
when the generator is used in a for-loop. Since that's likely to be
the majority of generators, I'd worry that accepting "return X" would
increase the occurrence of bugs caused by someone habitually writing
"return X" where they meant "yield X". (Assuming there's another yield
in the generator, otherwise it wouldn't be a generator and the error
would reveal itself very differently.)

> So, instead of having "return" automatically map to "raise StopIteration"
> inside generators, I'd like to suggest we keep it illegal to use "return"
> inside a generator, and instead add a new attribute "result" to StopIteration
> instances such that the following three conditions hold:
>
>       # Result is None if there is no argument to StopIteration
>       try:
>          raise StopIteration
>       except StopIteration, ex:
>          assert ex.result is None
>
>       # Result is the argument if there is exactly one argument
>       try:
>          raise StopIteration(expr)
>       except StopIteration, ex:
>          assert ex.result == ex.args[0]
>
>       # Result is the argument tuple if there are multiple arguments
>       try:
>          raise StopIteration(expr1, expr2)
>       except StopIteration, ex:
>          assert ex.result == ex.args
>
> This precisely parallels the behaviour of return statements:
>    return                 # Call returns None
>    return expr            # Call returns expr
>    return expr1, expr2    # Call returns (expr1, expr2)

This seems a bit overdesigned; I'd expect that the trampoline
scheduler could easily enough pick the args tuple apart to get the
same effect without adding another attribute unique to StopIteration.
I'd like to keep StopIteration really lightweight so it doesn't slow
down its use in other places.

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


More information about the Python-Dev mailing list