PEP 255: Simple Generators

David Eppstein eppstein at ics.uci.edu
Wed Jun 20 19:49:33 EDT 2001


I wrote:
> > I'm wondering if it wouldn't make sense to allow a non-empty return 
> > statement in a generator, with the semantics that the object being returned 
> > is itself some kind of iterator that is used to continue the sequence.
> > 
> > i.e.
> >     def integers(i):
> >         yield i
> >         return integers(i+1)

In article <16074dce.0106201512.5459e720 at posting.google.com>,
 jeff at ccvcorp.com (Jeff Shannon) replied:

> It seems to me that this would be better written as
> 
> def integers(i):
>     while 1:
>         yield i
>         i += 1
> 
> but I confess that I don't see offhand how either case generalizes to a 
> less-contrived example.  It doesn't *seem* to me that your proposal adds
> significant functionality...  but I'm not so familiar with functional 
> programming, so I'm likely missing something.   :)

Ok, another mathematical one:

    def collatz(i):
        yield i
        if i % 2 == 0:
            return collatz(i/2)
        else:
            return collatz(3*i+1)

Yes, of course, you could do it with a loop.  You can do anything with a 
loop, so what need is there for recursion or any other such programming 
language feature?  But I think the functional point of view is more clearly 
expressed here than with a loop.

Second example, more data-structural: since list comparison is 
lexicographic, max(x,y) where x and y are two lists should be well-defined.  
What about when x and y are not lists but some other kind of iterator?

    def maxgen(x,y):
        for pair in zip(x,y):
            yield max(pair[0],pair[1])
            if pair[0] > pair[1]:
                return x
            elif pair[1] > pair[0]:
                return y

(Note this is proof of concept rather than a good implementation, zip is 
only supposed to work for lists and this code doesn't deal with the issue 
of what happens if you get to the end of one iterator before deciding who 
wins.)  Again, you could do this by replacing each of the return stmts with 
a loop, but I think this is clearer.

Finally, some earlier messages in this thread requested a way to use the 
return statement to yield one last item and then stop.  That is, to 
abbreviate the idiom

    yield x
    return

Here's a way to do it with this definition of a nonempty generator return:

    return (x,)
-- 
David Eppstein       UC Irvine Dept. of Information & Computer Science
eppstein at ics.uci.edu http://www.ics.uci.edu/~eppstein/



More information about the Python-list mailing list