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

Maric Michaud maric at aristote.info
Wed Jul 30 11:09:01 CEST 2008


Le Tuesday 29 July 2008 23:48:31 giltay at gmail.com, vous avez écrit :
> Here's a function, print_members.  It's just something that takes some
> iterable and prints its members in XML.  It's special-cased so that an
> empty iterable gets an empty tag.  (This is a bit of a trivial
> example, I admit; the point is that the empty iterable is a special
> case.)
>
> def print_members(iterable):
>     if not iterable:
>         print '<members />'
>         return
>     print '<members>'
>     for item in iterable:
>         print '<item>%s</item>' % item
>     print '</members>'
>
>
... 
> So print_members can work on iterables that have no len(), and handle
> the special case of an empty iterable, as long as __nonzero__ is
> implemented.
>

But iterables can have no notion of emptiness too :

>>>[25]: print_members((e for e in range(0)))
<members>
</members>

Your function is just wrong assuming that, it should be written :

>>>[31]: def print_members(iterable):
    print '<members',
    empty = True
    for item in iterable:
        if empty :
            empty = False
            print '>'
        print '<item>%s</item>' % item
    print empty and '/>' or '</members>'
   ....:
   ....:

>>>[40]: print_members((e for e in range(0)))
<members />

>>>[41]: print_members((e for e in range(1)))
<members >
<item>0</item>
</members>



> Counterexample:
>
> While "if x" works well in some circumstances, I don't like using it
> for purely numeric types.  For instance, I have a mutable Signal class
> for doing some basic DSP.  Among other things, I can apply a DC offset
> to the signal (it just adds the offset to all the samples).  I have a
> special case for an offset of 0 so I don't have to loop through all
> the samples (I also have a two-pass remove_offset method that
> subtracts the average; if it's already properly centred, I can skip a
> step).
>
> class Signal:
>     [...]
>     def dc_offset(self, amount):
>         if amount == 0:
>             return
>         self.samples = [sample + amount for sample in self.samples]

This function is also wrong assuming that because amount compare to zero, it 
can be added to sample.

If you want to make type checking just check the type or convert your 
parameter to an int, but the test "== 0" is of no help here.

The only valuable point I see for this idiom is to make more explicit I am 
testing a numerical value.
But your example is a good objection to this, with well chosen name, ie. 
amount, it's quite clear "if not amount :" is testing the zero value of a 
numerical value.

-- 
_____________

Maric Michaud



More information about the Python-list mailing list