[Python-ideas] Revised**10 PEP on Yield-From
Jacob Holm
jh at improva.dk
Wed Apr 15 12:53:52 CEST 2009
Hi Greg
A few comments on the latest PEP 380 version (rev11d)...
1) IIRC, the use of sys.exc_info() is not needed in 3.x as all
exceptions have a __traceback__ attribute.
2) The expansion is not handling StopIterations raised as a result of
calling _i.throw(). They should be treated just like any other
StopIteration that ends the yield-from.
A simpler expansion based on 1) and 2) but otherwise identical is:
_i = iter(EXPR)
try:
_y = next(_i)
while 1:
try:
_s = yield _y
except GeneratorExit:
_m = getattr(_i, 'close', None)
if _m is not None:
_m()
raise
except BaseException as _e:
_m = getattr(_i, 'throw', None)
if _m is not None:
_y = _m(_e)
else:
raise
else:
if _s is None:
_y = next(_i)
else:
_y = _i.send(_s)
except StopIteration as _e:
_r = _e.value
RESULT = _r
3) If the subiterator has a close() but doesn't have throw() it won't be
closed when throw() is called on the outer generator. This is fine with
me, I am just not sure if it is intentional.
4) If the subiterator has a close() but doesn't have send() it won't be
closed when a send() on the outer generator causes an AttributeError in
the expansion. Again this is fine with me, I am just not sure if it is
intentional.
5) The last paragraph in the "Use of StopIteration to return values"
section, seems to be a leftover from an earlier draft of the PEP that
used a different exception.
6) Several of the issues we have been discussing on python-ideas are not
mentioned at all:
* The "initial next()" issue should at least be described and listed
as out of scope.
* The "what should close() do if it catches StopIteration with a
value" issue I don't think we have resolved either way. Since we
are not going to store the value, only the first close() would be
able to return it. Under those conditions, I no longer think that
returning the value is a good idea. If we are not storing or
returning the value, I think close() should raise an exception.
Either reraise the StopIteration, so that the caller has a chance
to get the value that way, or raise a RuntimeError, because it is
meaningless to return a value as response to a GeneratorExit when
that value cannot later be accessed by anything and it is
therefore most likely a bug.
* The special-casing of StopIteration should probably be mentioned
as a rejected idea. Not special-casing it does break the
refactoring principle, and I think it important to mention that in
some way.
* There may be other issues I have forgotten at the moment.
7) By not mentioning caching, you are effectively saying the methods
won't be cached. I have exactly one use for this. The fastest
pure-python "full" workaround I can find for the "initial next()" issue
is a wrapper using Nicks self-modifying class hack. With this the
delegation cost is less than 1/3 of any other approach I have tried.
(But still 13 times higher than a yield-from without the wrapper when
using your patch). All that means is that adding caching later would be
likely to break some code that relied on the exact semantics as
described in the PEP.
Other than that, everything looks fine.
Best regards
- Jacob
More information about the Python-ideas
mailing list