[Python-Dev] Suggested amendment to PEP 255
Barry A. Warsaw
Wed, 20 Jun 2001 12:35:49 -0400
>>>>> "GE" == Greg Ewing <email@example.com> 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? :)