My (late) beef with Simple Generator syntax (PEP 255)

Terry Reedy tjreedy at udel.edu
Thu Nov 14 02:57:36 EST 2002


"Cameron Horn" <camhorn at mac.com> wrote in message
news:mailman.1037240419.5238.python-list at python.org...
>>> If I want to write an empty generator, I write this(?):
>>> def foo():
>>>    return
>>>    yield "never"

<my previous comment clipped>

I prefer (see below for why)

def null():
  raise StopIteration
  yield 1/0

> Do you think that a generator that returns an empty iterator (i.e.,
one
> that has no elements, as written above) isn't valid or useful?   Or
that as
> written above doesn't make such a generator?

Yes, an empty iterator and a generator function that produces such
could occasionally be useful just like empty functions and classes.
And yes, I checked: your foo (and my null) are generator functions
that each produce a generator object whose next() method immediately
raises StopIteration when first called.

Directly writing an empty iterator class is easy: make 'raise
StopIteration' the only statement in the next method.  (A simple
return does not work here, so I prefer the same in a generator where
return does work.)  As you noticed, producing an empty iterator with a
generator function is less graceful even though its less work.  The
yield statement does double duty: flag that the function is a
generator and actually yield the value when is is 'converted' to an
iterator.  So you need a 'fake' yield after raising the exception to
do the first job even though you do not want to do the second.
Perhaps 'yield 1/0' makes it clearer that nothing is really yielded.

Whether or not a 'generator that returns an empty iterator' (which is
something) is itself 'empty' is a matter of definitional choice.
Because I understand the hidden trick, I see it as not, for the same
reason that [[]] is not null even though [] is.

Part of the problem here is that 'generator' is overloaded with three
related meanings.  We write a 'generator'.  Python compiles it into a
generator function with code that we did not write.  When called, that
function produces a generator object that follows the iterator
protocol and whose next method is a 'resumable function' containing
the code that we did write.  The latter two work together with the for
loop machinery to produce the illusion that the generator we write
acts like it seems to.  So when you used the phrase 'empty generator',
you may have been thinking most of meaning one while I substituted
meaning two.

Terry J. Reedy





More information about the Python-list mailing list