[Python-ideas] Revised**6 PEP on yield-from

Greg Ewing greg.ewing at canterbury.ac.nz
Sun Feb 22 11:25:33 CET 2009


Bruce Frederiksen wrote:
> Greg Ewing wrote:
>        If the sent value is
>>       not None, the iterator's ``send()`` method is called if it has
>>       one, otherwise an exception is raised in the delegating generator.
> 
> Shouldn't this define which exception is raised?

To put it more precisely, whatever exception results from
attempting to call the non-existent send() method is propagated
into the delegating generator.

> Intuitively, I would expect that the delegating generator would not see 
> this exception; as if the delegating generator itself lacked a send 
> method.

This would introduce an inconsistency between delegating to a
generator and delegating to some other kind of iterator.

When delegating to another generator, the inlining principle
requires that any exceptions raised by the subgenerator must be
propagated through the delegating generator. This includes
whatever exceptions might result from attempting to send values
to the subgenerator.

My feeling is that other iterators should behave the same way
as generators, as closely as possible, when delegated to.

There's also the consideration that the semantics you propose
can't be expressed in terms of a Python expansion, since there's
no way for a generator to throw an exception right out of itself
without triggering any except or finally blocks on the way.

While that's not a fatal flaw, I think it's highly desirable
to be able to specify the semantics in terms of an expansion,
because of its precision. Currently the expansion in the PEP
is the only precise and complete specification. It's very
hard to express all the nuances and ramifications in words
and be sure that you've covered everything -- as witnessed
by your comments above!

> OTOH, this may be a reason to just translate send to next for non-None 
> values too???  Perhaps the justification in that case would be to think 
> of it like sending to a yield *statement* (which can't accept the sent 
> value) -- which is not an error in generators.

That's a distinct possibility. Guido pointed out that there
is an existing case where send() refuses to accept anything
other than None, and that's when you call it immediately
after the generator starts.

But that case doesn't apply here, because the first call to a
delegated iterator is always made implicitly by the yield-from
expression itself. So a send() that gets delegated to a subiterator
is *never* the first call, and therefore it should ignore any sent
values that it doesn't care about.

In other words, go back to what I had in the first draft of
the PEP:

             if hasattr(_i, 'send'):
                 _u = _i.send(_v)
             else:
                 _u = _i.next()

or perhaps

             if _v is not None and hasattr(_i, 'send'):
                 _u = _i.send(_v)
             else:
                 _u = _i.next()

Guido, what do you think about this?

-- 
Greg



More information about the Python-ideas mailing list