Calling a generator multiple times

Tim Peters at
Mon Dec 10 00:49:36 CET 2001

> A BDFL Pronouncement is called for precisely in those areas where
> extended debate has proved that consensus will never be reached.  The
> choices then are eternal paralysis, or, if Guido wants something enough,
> he breaks the deadlock by Decree and life moves on.

> This is fair enough, and I can live with it.

That's good -- since the alternative appears to be death <wink>.

> It's not like generators are all that hard, or anything. And it's not
> that I think that the current _behavior_ of generators is wrong; rather,
> I'm flummoxed as to the leaving of the syntax as it is, as it leads to
> surprises.  The syntax as is predicts other behavior to me.
> For example, when I wrote my first generator, I knew _conceptually_
> exactly what to expect based on my prior use of stackless
> continuations, continuations in lisp, cooperative multi-threading
> environments I've written, and esoteric and ill-advised :) use of
> setjmp and longjmp in the past.

This isn't typical.  Most people coming to generators won't have any
relevant experience beyond vanilla function calls.  The syntax chosen
emphasizes the similarities to functions, not the differences.  In this
respect it follows the Icon language, which also makes no syntactic
distinction between generators and functions (although the reason for that
cuts deeper in Icon -- still, the conceptual distinction exists there too,
and the lack of multiple syntactic clues there hasn't been a problem for
them in real life either).

> However, what threw me was the behavior on the first invocation.
> Since I was defining a method, I expected that when called the
> first time the code prior to first yield would execute. That's
> not what happened. The code executed on the first next.

Sure, that's how they work, and it sounds like you also dived in at the deep
end.  The expected first use for generators is via:

    for whatever in generator():
        process whatever

Indeed, Icon and CLU both *restrict* generators to iteration contexts.
Tying it into Python's iteration protocol, and exposing .next(), are
advanced features.  Most users won't need to know about that.

> I can see perfectly well why it went the other way, but I certainly
> hope you can see how I would state that code appearing in a function
> definition probably ought to execute when the function is apparently
> called or someone is going to be surprised.

I'd be more sympathetic if it required great effort to get unconfused again;
but it doesn't, so I'm not more concerned about this than that, e.g.,
mutating methods of mutable objects generally return None (another thing you
were suprised by a few days ago).

> And they will be. I guarantee it. I'm willing to bet that almost
> every single new user of generators is going to encountered this
> and have the same experience of surprise.

Some will, some won't.  If they stick to generators in for-loops, the
question will never even arise -- "it just works" then.

> Will this _baffle_ anyone? Hell, no. It's not that hard to say
> "what the fuck!?", read the manual a little more carefully, and
> come to an understanding. It's not a _difficult_ concept to
> grasp, just an unexpected one.

Expectations come from prior experience, and you had too much <0.6 wink>.
These isn't Scheme, or even Stackless Python.  Most people will get their
expectations about how generators work from the Python docs.

More information about the Python-list mailing list