Boolean tests [was Re: Attack a sacred Python Cow]

Russ P. Russ.Paielli at gmail.com
Wed Jul 30 07:15:30 CEST 2008


On Jul 29, 9:52 pm, Carl Banks <pavlovevide... at gmail.com> wrote:
> On Jul 29, 11:17 pm, Terry Reedy <tjre... at udel.edu> wrote:
>
>
>
> > Carl Banks wrote:
> > >> As I wrote in the second reply email I sent, check out my integer set
> > >> recipe on ASPN (and to save you the search:  http://code.activestate.com/recipes/466286/).
>
> > > Couple points:
>
> > > 1. Any container type that returns a length that isn't exactly the
> > > number of elements in it is broken.
> > > 2. The need for __nonzero__ in this case depends on a limitation in
> > > the language.
> > > 3. On the other hand, I will concede that sometimes calculating len is
> > > a lot more expensive than determining emptiness, and at a basic level
> > > it's important to avoid these costs.  You have found a practical use
> > > case for __nonzero__.
>
> > I thought of another one: testing whether an iterator is 'empty' (will
> > raise StopIteration on the next next() (3.0) call) or not.  As virtual
> > collections, iterators generally have neither __len__ or __bool__.  But
> > __bool__ (but only __bool__) can be added to any iterator by wrapping it
> > with something like the following 3.0 code (not tested):
>
> > class look_ahead_it():
> >    def __init__(self, iterable):
> >      self.it = iter(iterable)
> >      self.fill_next()
>
> >    def __iter__(self):
> >      return self
> >    def __next__(self):
> >      tem = self.next
> >      if tem is self.empty:
> >        raise StopIteration
> >      else:
> >        self.fill_next()
> >        return tem
>
> >    empty = object()
> >    def fill_next(self)
> >      try:
> >        self.next = next(self.it)
> >      except StopIteration:
> >        self.next = self.empty
>
> >    def __bool__(self):
> >      return self.next is not self.empty
>
> Iterators are funny: if there's any reason you should not use "if x"
> it's because of them.  Built-in iterators are always true, so if
> you're writing a function that accepts an iterable you should never
> use the "if x" to test whether it's empty, because it fails for a
> whole class of iterables.
>
> However, given that that wart exists, your example does work for "if
> x" and not with "if len(x)!=0".
>
> Then again, it really only works to accommodate faulty code, because
> no code that expects an iterable should be using that test in the
> first place.  (Unless you wrap every iterable as soon as you get it,
> but then you're not bound to use __nonzero__.)
>
> Carl Banks

All this discussion about "if x" has me wondering. I use it all the
time because a fully explicit test just seems redundant. But maybe it
does have some value in terms of readability and type checking. After
all, it is possible to forget whether something is a number or a list.

Having said that, it would sure be nice to be able to write

if myList is not empty:

instead of

if len(myList) != 0:



More information about the Python-list mailing list