Truth value of iterators [was: question about True values)

Carl Banks pavlovevidence at gmail.com
Thu Oct 26 23:41:16 EDT 2006


Ben Finney wrote:
> "Carl Banks" <pavlovevidence at gmail.com> writes:
>
> > An iterator is not a sequence, and it's impossible to determine
> > whether an iterator is "empty" in general, except by trying to get
> > an item from it. [...]
> >
> > IMO, this is big time wart in the language.  Iterators have no
> > calculatable truth value; for many other types a truth value doesn't
> > make sense (for instance: function objects, type objects, modules,
> > user-defined types that don't bother with __nonzero__).  Using such
> > objects in a boolean context is almost always an error.
>
> It still seems like a reasonable thing for a programmer to do though,
> even if the language doesn't currently support it.
>
> Would it make sense to *define* a truth value for iterators? Or at
> least to enable those that *are* able to say "I'm empty" to do so in a
> way that boolean contexts can interpret as "false"?

Again, it's impossible to tell if an iterator is empty in general
except by trying to get an item.  You could add a feature to iterators
that fetches an item and stores it, but that would a. be a pain in the
neck for everyone, and b. adversely affect iterators that depend on
outside factors.

> Perhaps allowing (but not requiring) an iterator object to grow a
> 'len' method is the simplest way.

I could live with some iterators defining __len__ or even __nonzero__,
as long as iterators that couldn't determine these things threw an
exception rather than returning a fake value.  I'd rather no iterators
did this, though, because having these options makes it likely that
some programmers will write code supporting only "len-able iterators",
thus hindering polymorphism unnecessarily.  I'd rather people use
iterators as iterators and not as temporally-challenged lists.

However, it's certainly helpful sometimes to know if an iterator has
any items left (say, to possibly avoid some initialization code).  I
don't think this should be a part of iterator protocol, but maybe it'd
be nice if somewhere in the the standard library there was an iterator
type such as this:

class EmptySavvyIterator(object):
    noitem = object()
    def __init__(self,iterable):
        self.iterator = iter(iterable)
        self.storage = self.noitem
    def __iter__(self):
        return self
    def next(self):
        if self.storage is not self.noitem:
            item = self.storage
            self.storage = self.noitem
            return item
        return self.iterator.next()
    def empty(self):
        if self.storage is not self.noitem:
            return False
        try:
            self.storage = self.iterator.next()
        except StopIteration:
            return True
        return False
    # if you must...
    def __nonzero__(self):
        return not self.empty()


Carl Banks




More information about the Python-list mailing list