Rich Comparisons Gotcha
Rasmus Fogh
rhf22 at mole.bio.cam.ac.uk
Sun Dec 7 14:03:43 CET 2008
Jamed Stroud Wrote:
> Rasmus Fogh wrote:
>> Dear All,
>> For the first time I have come across a Python feature that seems
>> completely wrong. After the introduction of rich comparisons, equality
>> comparison does not have to return a truth value, and may indeed return
>> nothing at all and throw an error instead. As a result, code like
>> if foo == bar:
>> or
>> foo in alist
>> cannot be relied on to work.
>> This is clearly no accident. According to the documentation all
>> comparison operators are allowed to return non-booleans, or to throw
>> errors. There is
>> explicitly no guarantee that x == x is True.
> I'm not a computer scientist, so my language and perspective on the
> topic may be a bit naive, but I'll try to demonstrate my caveman
> understanding example.
> First, here is why the ability to throw an error is a feature:
> class Apple(object):
> def __init__(self, appleness):
> self.appleness = appleness
> def __cmp__(self, other):
> assert isinstance(other, Apple), 'must compare apples to apples'
> return cmp(self.appleness, other.appleness)
> class Orange(object): pass
> Apple(42) == Orange()
True, but that does not hold for __eq__, only for __cmp__, and
for__gt__, __le__, etc.
Consider:
Class Apple(object):
def __init__(self, appleness):
self.appleness = appleness
def __gt__(self, other):
assert isinstance(other, Apple), 'must compare apples to apples'
return (self.appleness > other.appleness)
def __eq__(self, other):
if isinstance(other, Apple):
return (self.appleness == other.appleness)
else:
return False
> Second, consider that any value in python also evaluates to a truth
> value in boolean context.
>
> Third, every function returns something. A function's returning nothing
> is not a possibility in the python language. None is something but
> evaluates to False in boolean context.
Indeed. The requirement would be not that return_value was a boolean, but
that bool(return_value) was defined and gave the correct result. I
understand that in some old Numeric/numpy version the numpy array __eq__
function returned a non-empty array, so that
bool(numarray1 == numarray2)
was true for any pair of arguments, which is one way of breaking '=='.
In current numpy, even
bool(numarray1 == 1)
throws an error, which is another way of breaking '=='.
>> But surely you can define an equal/unequal classification for all
>> types of object, if you want to?
> This reminds me of complex numbers: would 4 + 4i be equal to sqrt(32)?
> Even in the realm of pure mathematics, the generality of objects (i.e.
> numbers) can not be assumed.
It sounds like that problem is simpler in computing. sqrt(32) evaluates to
5.6568542494923806 on my computer. A complex number c with non-zero
imaginary part would be unequal to sqrt(32) even if it so happened that
c*c==32.
Yours,
Rasmus
---------------------------------------------------------------------------
Dr. Rasmus H. Fogh Email: r.h.fogh at bioc.cam.ac.uk
Dept. of Biochemistry, University of Cambridge,
80 Tennis Court Road, Cambridge CB2 1GA, UK. FAX (01223)766002
More information about the Python-list
mailing list