[Python-Dev] Re: PEP 279

Raymond Hettinger python@rcn.com
Sat, 30 Mar 2002 08:55:24 -0500


[Tim]
> So I'd like to keep
> generators simple.

I hear you.

> Generator exceptions do less damage (IMO) to simplicity than some of the
> other extensions, but in practice, in the very few cases I've wanted
> something like that, this worked fine:
>
> class Whatever:
>     def __init__(self):
>         self._stop = 0
>
>     def stop(self):
>         self._stop = 1
>
>     def generator(self):
>         while 1:
>             ...
>             yield something
>             if self._stop:
>                 break
>         cleanup

Hmm, the client code needs to maintain TWO instance variables, the generator
object and the instance of Whatever.  It works but doesn't smell right to
me:

w = Whatever()
wg = w.generator()
wg.next()
wg.next()
w.stop(); wg.next()    # trigger clean-up

> Bingo.  If you want coroutines, design a coroutine facility.  Piling more
> semantics on to "yield" takes a delightfully simple yet powerful gimmick
and
> hides it under ten kinds of obscurity.

I don't see the obscurity.  This is the kind of tool that is invisible and
out
of the way until the one day you really need it and the tool is right there
in your hand (as if by time machine).

Throw wouldn't be used 98% of the time.  So, simple things are left simple
and hard things are a little less hard.  I didn't come up with these ideas
out of the ether.  It came up in a real world application for producing
index prints from jpegs.

That being said, I accept that generator parameter passing and exception
passing are doomed.

Here is my alternate proposal that is much simpler and doesn't encourage
weirdness.
[Developers feel free to stomp on the idea but please don't smack me around
for thinking it up].


Specification for Generator Attributes:

    1. Allow attributes to be assigned to generator objects.

    2.  Provide a means of accessing those attributes from within the
    generator by using a reference to __self__.

 def mygen():
     print __self__.greeting
     yield 'hello'
     print __self__.greeting

 g = mygen()
 g.greeting = 'Good morning'
 print g.next()
 g.greeting = 'Good night'

Advantages:  Uses the standard python attribute assignment idiom so there is
no learning curve and no surprises.  Easily implementable without new
keywords, new builtins, or parser magic.  Provides a data sharing solution
that avoids the yield / next() matching problem, avoids enclosing classes,
and avoid global variables.  Simple and neat.
Disads:  Introduces a new system variable, __self__.



Raymond Hettinger, CPA



P.S.  No one needs to say anything mean to make me go away.  This is the
last generator proposal and then I'm back off to volunteering on Py-Help
and co-authoring a Python book update.