[Python-ideas] Possible PEP 380 tweak
Ron Adam
rrr at ronadam.com
Sat Oct 30 18:54:15 CEST 2010
On 10/30/2010 02:58 AM, Nick Coghlan wrote:
> On Sat, Oct 30, 2010 at 4:42 PM, Ron Adam<rrr at ronadam.com> wrote:
>> Ok, after thinking about this for a while, I think the "yield from" would be
>> too limited if it could only be used for consumers that must run until the
>> end. That rules out a whole lot of pipes, filters and other things that
>> consume-some, emit-some, consume-some_more, and emit-some_more.
>
> Indeed, the "stop-in-the-middle" aspect is tricky, but is the crux of
> what we're struggling with here.
>
>> I think I figured out something that may be more flexible and insn't too
>> complicated.
>
> Basically a way to use yield from, while declaring how to force the
> end of iteration? Interesting idea.
Not iteration, iteration can continue. It signals the end of delegation,
and returns control to the generator that initiated the delegation.
> However, I think sentinel values are likely a better way to handle
> this in a pure PEP 380 context.
Sentinel values aren't always better because they require a extra
comparison on each item.
>> Here's an example.
>
> Modifying this example to use sentinel values rather than throwing in
> exceptions actually makes it all fairly straightforward in a PEP 380
> context. So maybe the moral of this whole thread is really "sentinel
> values good, sentinel exceptions bad".
>
> # Helper function to finish off a generator by sending a sentinel value
> def finish(g, sentinel=None):
> try:
> g.send(sentinel)
> except StopIteration as ex:
> return ex.value
>
> def gtally(end_tally=None):
> # Tallies numbers until sentinel is passed in
> count = tally = 0
> value = object()
Left over from earlier edit?
> while 1:
> value = yield
> if value is end_tally:
> return count, tally
> count += 1
> tally += value
The comparison is executed on every loop. A try-except would be outside
the loop.
> def gaverage(end_avg=None):
> count, tally = (yield from gtally(end_avg))
> return tally / count
>
> def main():
> g = gaverage()
> next(g)
> for x in range(100):
> g.send(x)
> return finish(g)
Cheers,
Ron
More information about the Python-ideas
mailing list