# Rich Comparisons Gotcha

Steven D'Aprano steven at REMOVE.THIS.cybersource.com.au
Thu Dec 11 04:28:02 CET 2008

```On Wed, 10 Dec 2008 17:21:51 -0500, Luis Zarrabeitia wrote:

> I do numeric work... I'm finishing my MSc in applied math and I'm
> programing mostly with python. And I'd rather have a.compare_with(b), or
> a.elementwise_compare(b), or whatever name, rather than (a==b).all().

Unluckily for you, the Numeric/Numpy people wanted something else. They
asked first, there's a lot more of them, and their project is very
important to Python's continued success.

> In
> fact, I'd very much like to have an a.compare_with(b, epsilon=e).all()
> (to account for rounding errors), and with python2.5,
> all(a.compare_with(b)).
>
> Yes, I could create an element_compare(a,b) function.

Absolutely.

> But I still can't use a==b and have a meaningful result.

That's right. *ANY* operation in Python can fail, given arbitrary data,
with the possible exception of the id() function and the "is" and "is
not" operators. You have to deal with it.

> Ok, I can (and do) ignore that,
> it's just one library, I'll keep track of the types before asking for
> equality (already an ugly thing to do in python), but the a==b behaviour
> breaks the lists (a in ll, ll.indexof(a)) even for elements not in
> numpy. ¿Should I also ignore lists?

That depends on what sort of contract your code is giving. Does it
promise to work with any imaginable data whatsoever, no matter how badly
broken or poorly designed or incompatible with what you're trying to do?

If so, then I suggest your contract is broken, not the behaviour of list.
You can't make trustworthy promises to deal with arbitrary data types
that you don't control, that can fail in arbitrary ways. Here's something
for you to consider:

class Boobytrap:
def __eq__(self, other):
if other == 1:
return True
elif other == 2:
while True:
pass
return False

>>> alist = [0, Boobytrap(), 2, 3]
>>> 1 in alist
True
>>> 3 in alist
True
>>> 5 in alist
False
>>> 2 in alist

What do you expect should happen?

> The concept of equality between two arrays is very well defined, as it
> is also very well defined the element-by-element comparison. There is a
> need to test for both - then the way to test for equality should be the
> equality test.

The Numpy people disagree with you. It was from their request that Python
was changed to allow __eq__ to return arbitrary objects.

--
Steven

```