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