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

Steven D'Aprano steve at REMOVE-THIS-cybersource.com.au
Wed Jul 30 22:54:41 EDT 2008


On Wed, 30 Jul 2008 20:55:03 +0100, Matthew Woodcraft wrote:

> On the other hand, iterators provide a clear example of problems with
> "if x": __nonzero__ for iterators (in general) returns True even if they
> are 'empty'.

How do you propose telling whether an iterator is empty?

That's a generic problem with any sort of lazy function. You don't know 
if it has finished unless you try grabbing data from it.



> For example, this function (which attempts to avoid making an expensive
> call when not necessary) is buggy, but easy to write if you've been
> taught that "if x" will work with any kind of object.
> 
> def frob(widgets, power):
>     if widgets:
>         frobber = Frobber(power) # expensive call
>         for widget in widgets:
>             frobber.frob(widget)


AFAIK there's no great solution to this problem. It's inherent in the way 
lazy functions work. Certainly you can't replace the call to "if widgets" 
with "if len(widgets)", because iterators don't have a length.

However, there is a good (but not great) solution:

def frob(widgets, power):
    widgets = iter(widgets)  # in case widgets is a sequence
    try:
        first = widgets.next()
    except StopIteration:
        # empty iterator, nothing to do
        return None
    frobber = Frobber(power) # expensive call
    frobber.frob(widget)
    for widget in widgets:
        frobber.frob(widget)


-- 
Steven



More information about the Python-list mailing list