[Python-ideas] Raise StopIteration with same value on subsequent `next`s

Franklin? Lee leewangzhong+python at gmail.com
Mon Dec 11 04:10:20 EST 2017


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):
        try:
            next(gen)
        except StopIteration as e:
            return e.value
        else:
            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.


More information about the Python-ideas mailing list