[Python-Dev] Suggested amendment to PEP 255

Barry A. Warsaw barry@digicool.com
Wed, 20 Jun 2001 12:35:49 -0400

>>>>> "GE" == Greg Ewing <greg@cosc.canterbury.ac.nz> writes:

    GE> What matters to the caller is irrelevant here. We're talking
    GE> about what matters to someone writing or reading the 
    GE> implementation. To those people, there is a VERY big 
    GE> difference between a regular function and a 
    GE> generator-function -- about as big as the difference 
    GE> between a class and a function!

    GE> In fact, a generator-function is in many ways much more
    GE> like a class than a function. Calling a generator-function
    GE> doesn't execute any of the code in its body; instead, it
    GE> creates an instance of the generator, much like calling
    GE> a class creates an instance of the class. Calling them
    GE> "generator classes" and "generator instances" would
    GE> perhaps be more appropriate, and more suggestive of the
    GE> way they actually behave.

Thanks Greg, I think you've captured perfectly my discomfort with the
proposal.  I'm fine with return being "special" inside a generator,
along with most of the other details of the pep.  But it bugs me that
the semantics of calling the thing created by `def' is different
depending on some statement embedded deep in the body of the code.

Think about it from a teaching perspective: You're taught that def
creates a function, perhaps called foo.  You know that calling foo
starts execution at the first line in the function block.  You know
you can put a print statement on the first line and it will print
something out when the function is called.  You know that you can set
a debugger break point at foo's first line and when you call the
function, the debugger will leave you on that first line of code.

But all that changes with a generator!  My print statement isn't
executed when I call the function... how weird!  Hey, the debugger
doesn't even break on the line when I call the function.  Okay, maybe
it's some /other/ foo my program is really calling.  So let's hunt
around for other possible foo's that my program might be calling.
Hmm, no dice there.  Now I'm really confused because I haven't gotten
to the chapter that says "Now that you know all about functions,
forget most of that if you find a yield statement in the body of the
function, because it's a special kind of function called a generator.
Calling such a special function doesn't execute any code, it just
instantiates a built-in object called a generator object.  To get any
of the generator's code to execute, you have to call the generator
object's next() method."

Further, I print out the type of the object returned by calling foo
and I see it's a <generator object at 0x9999999>.  Okay, so now let me
search foo for a return statement.  Because I know about functions,
and I know that the returned object isn't None, I know that the
function isn't falling off the end.  So there must be a return
statement that explicitly returns a generator object (whatever that
is).  Hmm, nope, there's just a bare return sitting there.  That's
damn confusing.  I wonder what those yield statements are doing.
Well, I look those up in my book's index and I see that's described in
chapter 57, which I haven't gotten to yet.  Besides, those yields
clearly have integers after them, so that can't be it.  So how the
heck do I get a generator object by calling this function???

You'll counter that the "search for yield to find out if the function
is special" is a simple rule, once learned is easily remembered.  I'll
counter that it's harder for me to do an Isearch in XEmacs to find out
what kind of thing foo is. :)

To me, it's just bad mojo to have the behavior of the thing created by
`def' determined by what's embedded in the body of the program.  I
don't buy the defint argument, because by searching for a return
statement in the function, you can find out exactly what is being
returned when the function is called.  Not so with a generator.

My vote is for a "generator" keyword to introduce the code block of a
generator.  Makes perfect sense to me, and it will be a strong
indication to anybody reading my code that something special is going
on.  And something special /is/ going on!

An informal poll of PythonLabs indicates a split on this subject,
perhaps setting Jeremy up as a Sandra Day O'Conner swing vote.  But
who said this was a democracy anyway? :)

somewhat-like-my-own-country-of-origin-ly y'rs,