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

sismex01 at hebmex.com sismex01 at hebmex.com
Wed Nov 13 17:45:08 EST 2002


> From: Cameron Horn [mailto:camhorn at mac.com]
> Sent: Wednesday, November 13, 2002 4:38 PM
>  
> On Wednesday, Nov 13, 2002, at 02:26PM, <sismex01 at hebmex.com> wrote:
> 
> >> From: Cameron Horn [mailto:camhorn at mac.com]
> >> Sent: Wednesday, November 13, 2002 4:26 PM
> >>  
> >> On Wednesday, Nov 13, 2002, at 02:19PM, 
> <sismex01 at hebmex.com> wrote:
> >> 
> >> >> From: Cameron Horn [mailto:camhorn at mac.com]
> >> >> Sent: Wednesday, November 13, 2002 4:20 PM
> >> >>  
> >> >> On Wednesday, Nov 13, 2002, at 02:16PM, David Eppstein 
> >> >> <eppstein at ics.uci.edu> wrote:
> >> >> 
> >> >> >On 11/13/02 2:11 PM -0800 Cameron Horn <camhorn at mac.com> wrote:
> >> >> >>> What I wonder is, why does it need to be a generator?  
> >> >> What's wrong with
> >> >> >>> def foo(): return ( )
> >> >> >>> ?
> >> >> >>
> >> >> >> You're right if it's a one-time thing.  However, if 
> I've got a
> >> >> >> scaffolding like this, then it matters.
> >> >> >>
> >> >> >> def process_generator(function):
> >> >> >>    for x in function():
> >> >> >>       print x
> >> >> >
> >> >> >How does the function foo() I defined above fail to 
> work in this 
> >> >> >scaffolding?
> >> >> 
> >> >> In the "TypeError: iteration over non-sequence" sort of way.
> >> >>
> >> >
> >> >An empty tuple is a sequence also;
> >> >
> >> >the "return ( )" thing is returning an empty tuple,
> >> >not "None".  You can make it clearer by using
> >> >"return tuple()" rather than "return ()".
> >> 
> >> Oops.  Missed those parentheses.  Then it is completely 
> >> useful, unless you end up using the "next" method.
> >>
> >
> >In that case, if you reckon you're going to use .next()
> >directly, then you should change 'foo' to something like
> >the following:
> >
> >def foo(): return iter(tuple())
> >
> >It's going to return a valid iterator which is going to
> >try to iterate through an empty tuple, so it's going
> >to raise StopIteration the first time you call .next().
> >
> >
> 
> Which is the obvious, clear and consistent way to create a 
> generator that doesn't do anything.  Unless you're checking 
> types or doing any other low-level things that you probably 
> oughtn't.  I return to my original point.  And then, since 
> everything works and I'm just complaining about a tiny bit of 
> syntax, I shut up.
> 

Interesting coincidence.

I'm thinking of applying generators for a server application I'm
creating, in which I'd use generators to simulate threading, like
the cooperative multithreading available in Forth.

It seems quite easy to just append all the generators that the
application receives, kind of like tasks, into a list, and
item by item, pop(0) it, do a .next(), and reappend it.

The question is, what is more efficient:

# Case one: enter a for loop and immediately break after
# reappending to the tasks list; if the generator raises
# StopIteration(), the append will never happen.
gen = tasks_list.pop(0)
for _ in gen:
   tasks_list.append(gen)
   break


# Case two: use try-except.
gen = tasks_list.pop(0)
try:
   gen.next()
   tasks_list.append(gen)
except StopIteration:
   pass


Lets see what happens in a while.

-gustavo




More information about the Python-list mailing list