Boolean tests [was Re: Attack a sacred Python Cow]
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:
if len(myList) != 0:
More information about the Python-list