[Python-ideas] Possible PEP 380 tweak

Guido van Rossum guido at python.org
Fri Oct 29 04:21:27 CEST 2010

On Thu, Oct 28, 2010 at 6:17 PM, Nick Coghlan <ncoghlan at gmail.com> wrote:
> On Fri, Oct 29, 2010 at 1:04 AM, Guido van Rossum <guido at python.org> wrote:
>> On Thu, Oct 28, 2010 at 5:44 AM, Nick Coghlan <ncoghlan at gmail.com> wrote:
>>> Yep, we've basically agreed on that as the way forward as well. We
>>> have a small tweak to suggest for PEP 380 to avoid losing the return
>>> value from inner close() calls,
>> This is my "gclose()" function, right? Or is there more to it?
> Yeah, the idea your gclose(), plus one extra tweak to the expansion of
> "yield from" to store the result of the inner close() call on a new
> GeneratorExit instance.
> To use a toy example:
>  # Even this toy framework needs a little structure
>  class EndSum(Exception): pass
>  def gsum():
>    # Sums sent values until EndSum or GeneratorExit are thrown in
>    tally = 0
>    try:
>      while 1:
>        tally += yield
>    except (EndSum, GeneratorExit):
>      pass
>    return x

You meant return tally. Right?

>  def average_sums():
>    # Advances to a new sum when EndSum is thrown in
>    # Finishes the last sum and averages them all when GeneratorExit
> is thrown in
>    sums = []
>    try:
>      while 1:
>        sums.append(yield from gsum())
>    except GeneratorExit as ex:
>      # Our proposed expansion tweak is to enable the next line
>      sums.append(ex.args[0])
>    return sum(sums) / len(sums)

Hmmm... That looks pretty complicated. Wouldn't it be much more
straightforward if instead of

 value ... value EndSum value ... value EndSum value ... value GeneratorExit

the input sequence was required to be

 value ... value EndSum value ... value EndSum value ... value
*EndSum* GeneratorExit


Then gsum() wouldn't have to catch EndSum at all, and I don't think
the PEP would have to special-case GeneratorExit. average_sums() could
simply have

  except GeneratorExit:
    return sum(sums) / len(sums)

After all this is a fairly arbitrary protocol and the caller
presumably can do whatever is required of it. If there are values
between the last EndSum and the last GeneratorExit those will be
ignored -- that is a case of garbage in garbage out. If you really
wanted to catch that mistake there would be several ways to translate
it reliably into some other exception -- or log it, or whatever.

It is also defensible that a better design of the protocol would not
require throwing EndSum but sending some agreed-upon marker value.

--Guido van Rossum (python.org/~guido)

More information about the Python-ideas mailing list