Interesting little "gotcha" with generators

K

Kenneth McDonald

I recently had need to write the following code:

def compileOuter(self):
if False: yield None
else: return

"compileOuter" is a generator function which is implemented in
various classes. In this particular class, it always yields nothing.
However, none of the following work:

def compileOuter(self):
return

def compileOuter(self):
pass

def compileOuter(self):
yield

The first two don't work because in order to define a generator, you
must have a yield statement inside it. The last doesn't work because
every "yield" must have an argument.

I've been using "return" in generators ever since I started using
generators, but on reflection, it seems to me that such a thing is in
some ways inconsistent; "return" is (conceptually, at least
originally) a function statement, where "return" by itself really
stands in for "return None". But in generators, it is being used as a
control flow command. For example, you can't have "return" with an
argument inside a generator.

Too bad "return" wasn't entirely forbidden within generators, and
"yield" without an argument mandated instead. Oh well, too let now I
suppose...


Cheers,
Ken
 
D

Duncan Booth

Kenneth said:
I recently had need to write the following code:

def compileOuter(self):
if False: yield None
else: return

"compileOuter" is a generator function which is implemented in
various classes. In this particular class, it always yields nothing.
However, none of the following work:

def compileOuter(self):
return

def compileOuter(self):
pass

def compileOuter(self):
yield

This would work:

def compileOuter(self):
return iter(())

and depending on how it is used, you might also get away with:

def compileOuter(self):
return []

A generator is simply a function which when called returns an iterator, so
you can use any other function which returns an iterator in its place.
 
W

Will McGugan

Kenneth said:
I recently had need to write the following code:

def compileOuter(self):
if False: yield None
else: return

"compileOuter" is a generator function which is implemented in various
classes. In this particular class, it always yields nothing. However,
none of the following work:

def compileOuter(self):
return

def compileOuter(self):
pass

def compileOuter(self):
yield

The first two don't work because in order to define a generator, you
must have a yield statement inside it. The last doesn't work because
every "yield" must have an argument.

I've been using "return" in generators ever since I started using
generators, but on reflection, it seems to me that such a thing is in
some ways inconsistent; "return" is (conceptually, at least originally)
a function statement, where "return" by itself really stands in for
"return None". But in generators, it is being used as a control flow
command. For example, you can't have "return" with an argument inside a
generator.

Too bad "return" wasn't entirely forbidden within generators, and
"yield" without an argument mandated instead. Oh well, too let now I
suppose...

Would this work?

def compilerOuter(self):
raise StopIteration

Will McGugan
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,274
Messages
2,571,368
Members
48,060
Latest member
JerrodSimc

Latest Threads

Top