[Tutor] Re: [Edu-sig] style question

Michael P. Reilly arcege@speakeasy.net
Thu, 21 Feb 2002 08:39:17 -0500


On Wed, Feb 20, 2002 at 03:50:44PM -0800, Kirby Urner wrote:
> 
> >
> >What's better is to get the length of the list where the value is true.
> >
> >how_many_evens = len( filter(lambda i, i%2==0, testlist) )
> >
> >   -Arcege
> 
> As yet, I don't get the real difference between getting the
> length by filtering on i%2==0, and adding the 1s in
> reduce(add,[i%2==0 for i in testlist]).  I'm missing some
> subtle point.

There are two points here that I've made.  One was pretty much hidden,
but I'll expand on it a bit.  The other is technical, but not as subtle.

The technical first since it is more straight-forward.

Given the following code:
$ cat try.py
#!/opt/local/bin/python2.1

import operator

class N:
  def __init__(self, n):
    self._n = n
  def __repr__(self):
    return 'N(%d)' % self._n
  def __mod__(self, other):
    return self.__class__(self._n % other)
  def __eq__(self, other):
    """Return a scaled truth value that will be used for other reasons."""
    return (self._n == other) and 100 or 0

def evenp(i):
  return i % 2 == 0

numbers = map(N, range(10))

print numbers
print filter(evenp, numbers)
print map(evenp, numbers)
print reduce(operator.add, map(evenp, numbers))

$ python2.1 try.py
[N(0), N(1), N(2), N(3), N(4), N(5), N(6), N(7), N(8), N(9)]
[N(0), N(2), N(4), N(6), N(8)]
[100, 0, 100, 0, 100, 0, 100, 0, 100, 0]
500
$

Right now, your code might be okay.  But later on, if you use the same
mechanism (addition of a boolean) with some other "integer" object,
then you could easily run into problems.  The class itself is fine and
follows all the rules, the algorithm for counting the number of true
values is flawed.

Now lets say that I change the __eq__ method to:
  def __eq__(self, other):
    return (self._n == other) and "true" or ""

It is still valid, but you'd get "truetruetrueutruetrue" instead of 5.

The less subtle point is one of code readability and code longevity.
Someone may have to read some future code that you write someday.
This used to be a major problem with Perl web programming (and probably
still is) - using language "tricks" that let you do things, but that
people look at and wonder "why."

Let's use one of the original working mechanisms someone contributed:

def count_evens(list):
  from operator import add
  return reduce(add, [i%2==0 for i in list])

Someone who does not normally think of 'boolean arithmetic' (as opposed to
'boolean algebra') would probably think that you are trying to add
actual integer values and not booleans and assume that the '==' operator
is a bug in your code.

Using 'boolean arithmetic' is against most algorithms, so when most people
see it, they'll probably think it is not what you meant and try to figure
out what it is doing.

I hope this is sufficiently long winded enough.  I have to run to a
doctor's appointment anyway.

  -Arcege