bool evaluations of generators vs lists

Albert Hopkins marduk at letterboxes.org
Tue Feb 10 16:25:47 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. 

Well, I did not implement generators in python, but my guess would be
that lists and tuples can be checked with len() to see if it is
non-empty.  Generators don't have length.  You would at least need to
call .next() which "changes" the generator so every time you'd want to
evaluate the boolean of the generator you'd potentially lose the next
item.

Generators are meant to replace lists where you don't want/can't put the
entire "list" in memory or for which there is no (known) end to the
list. You don't know the next value a generator will return (if any)
until you evaluate it.  Don't think of generators as containers like
lists, tuples and strings are.  Generators don't "contain" values.
Generators are objects that return the "next" value.  It has no idea how
many values it contains (it's not a container).  It only knows the
".next()" value when it's called.  It forgets the value once it's
returned. And it has no idea how far it is in the iteration until it's
finished (StopIteration).

> 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):

l = list(generator_object)

but in doing so you've (obviously) lost the advantages of the generator.


> Is there another list I should be asking these questions on?

I don't know. Sorry I wasn't able to help you.

-a





More information about the Python-list mailing list