bool evaluations of generators vs lists

Gabriel Genellina gagsl-py2 at yahoo.com.ar
Wed Feb 11 00:07:31 EST 2009


On Tue, 2009-02-10 at 12:50 -0800, Josh Dukes wrote:

>> The thing I don't understand is why a generator that has no iterable
>> values is different from an empty list. Why shouldn't bool ==
>> has_value?? Technically a list, a tuple, and a string are also objects
>> but if they lack values they're evaluated as False. It seems to me that
>> a generator is an object that intends to replace lists where lazy
>> evaluation would be more efficent. Here is one place where that's
>> definitely true.

Just in case it's not perfectly clear: until you call next() there is no  
way to know whether the generator will yield any value or not -- and once  
it does, it's lost until you explicitely save it.

This generator doesn't yield any value - but you have to wait for a while  
if you call .next() on it, until eventually raises StopIteration:
(x for x in xrange(2000000000) if x>100000000000)


En Tue, 10 Feb 2009 19:25:47 -0200, Albert Hopkins  
<marduk at letterboxes.org> escribió:

>> The main reason I'm interested in this is that it improves performance
>> immensely over boolean evaluation of large lists (as the attached code
>> shows). It seems to me if I could use find a good use for it in my
>> experimentation that someone else might also want to do the same thing
>> in real-world code.
>
> I don't understand what you mean by this.  But if you really want to
> know if a generator is "non-empty":
>
> def non_empty(virgin_generator):
>     try:
>         virgin_generator.next() # note you just lost the first value
>         return True
>     except StopIteration:
>         return False
>
> The only way to get around this is to put all the values of a generator
> inside a container (e.g. a list):

For a long generator you may not want to do that, also you may not want to  
lose the next element. A variation of your function above is useful in  
such cases:

py> def end_of_gen(g):
...   """returns (False, next_element) when it exists or (True, None) when  
it's
empty"""
...   try: return False, g.next()
...   except StopIteration: return True, None
...
py> g = (c for c in "Python" if c in "aeiou")
py> eog, c = end_of_gen(g)
py> eog
False
py> c
'o'
py> eog, c = end_of_gen(g)
py> eog
True
py> c


-- 
Gabriel Genellina




More information about the Python-list mailing list