[Python-ideas] Yield-From: Finalization guarantees
Jacob Holm
jh at improva.dk
Wed Apr 1 03:45:25 CEST 2009
Greg Ewing wrote:
> Jacob Holm wrote:
>
>> will also remove some behavior that could have been useful, such as
>> the ability to suppress the GeneratorExit if you know what you are
>> doing.
>
> I'm not convinced there are any use cases for suppressing
> GeneratorExit in the first place. Can you provide an
> example that couldn't be easily done some other way?
I don't have any real use cases, just a few examples of things you can
do in #2 that become a bit uglier in #3 or #4. This:
def inner():
try:
for i in xrange(10):
yield i
except GeneratorExit:
return i
return "all"
def outer():
val = yield from inner()
print val
return val
Does not behave like you would expect because the "return i" is
swallowed by the call to inner.close() (or is it?) and the "print val"
and "return val" statements are skipped due to the reraised
GeneratorExit. To get the a value out of the generator being closed you
need to raise and catch your own exception:
class Return(Exception): pass
def inner():
try:
for i in xrange(10):
yield i
except GeneratorExit:
raise Return(i)
return "all"
def outer():
try:
val = yield from inner()
except Return as r:
val = r.args[0]
print val
return val
This is certainly doable, but ugly compared to the version using return.
Here is an idea that would help this a little bit. We could change close
to return the value (if any) returned by the generator, and then attach
that value to the reraised GeneratorExit in the yield-from expansion.
That would allow the example to be rewritten as:
def inner():
try:
for i in xrange(10):
yield i
except GeneratorExit:
return i
return "all"
def outer():
try:
val = yield from inner()
except GeneratorExit as e:
val = e.value
print val
return val
Which I think is much nicer.
- Jacob
More information about the Python-ideas
mailing list