IIRC we considered this when we designed this (PEP 380) and decided that hanging on to the exception object longer than necessary was not in our best interest.

On Mon, Dec 11, 2017 at 1:10 AM, Franklin? Lee <leewangzhong+python@gmail.com> wrote:
Consider the following code, which creates a generator that
immediately returns 1, and then catches the StopIteration twice.

    def generatorfunction():
        if False: yield
        return 1

    def get_return(gen):
        except StopIteration as e:
            return e.value
            raise ValueError("Generator was not ready to stop.")

    gen = generatorfunction()
    get_return(gen) #=> 1
    get_return(gen) #=> None

The first time StopIteration is raised, it contains the returned
value. If StopIteration is forced again, the value is missing.

What about keeping the return value for subsequent raises? Perhaps as
an attribute on the generator object? The main disadvantage is that
it'd add another reference, keeping the return value alive as long as
the generator is alive. However, I don't think you'll want to keep a
dead generator around anyway.

Note: Javascript, which added generators, agrees with the Python
status quo: the return value is only available on the first stop. C#
does not have the concept of returning from an iterator.


Background: I made a trampoline for a toy problem, using generators as
coroutines to recurse.

When it came time to memoize it, I had to couple the memoization with
the trampoline, because I could not cache the answer before it was
computed, and I could not cache the generator object because it would
not remember its return value later.

I would have attached the returned value to the generator object, but
for some reason, generator and coroutine objects can't take
attributes. Maybe I should ask for that feature instead.

Either feature would allow the concept of a coroutine that is also a thunk.
Python-ideas mailing list
Code of Conduct: http://python.org/psf/codeofconduct/

--Guido van Rossum (python.org/~guido)