Terry Reedy 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.
You have touched on a real and known issue that accompanies dynamic
typing and the design of Python. *Every* Python function can return any
Python object and may raise any exception either actively, by design, or
passively, by not catching exceptions raised in the functions *it* calls.
Personally I would like to get these [EMAIL PROTECTED]&* misfeatures removed,
What you are calling a misfeature is an absence, not a presence that can
be removed.
That's not quite true. Rich comparisons explicitly allow non-boolean return
values. Breaking up __cmp__ into multiple __special__ methods was not the sole
purpose of rich comparisons. One of the prime examples at the time was numpy
(well, Numeric at the time). We wanted to use == to be able to return an array
with boolean values where the two operand arrays were equal. E.g.
In [1]: from numpy import *
In [2]: array([1, 2, 3]) == array([4, 2, 3])
Out[2]: array([False, True, True], dtype=bool)
SQLAlchemy uses these operators to build up objects that will be turned into SQL
expressions.
>>> print users.c.id==addresses.c.user_id
users.id = addresses.user_id
Basically, the idea was to turn these operators into full-fledged operators like
+-/*. Returning a non-boolean violates neither the letter, nor the spirit of the
feature.
Unfortunately, if you do overload __eq__ to build up expressions or whatnot, the
other places where users of __eq__ are implicitly expecting a boolean break.
While I was (and am) a supporter of rich comparisons, I feel Rasmus's pain from
time to time. It would be nice to have an alternate method to express the
boolean "yes, this thing is equal in value to that other thing". Unfortunately,
I haven't figured out a good way to fit it in now without sacrificing rich
comparisons entirely.
and constrain the __eq__ function to always return a truth value.
It is impossible to do that with certainty by any mechanical
creation-time checking. So the implementation of operator.eq would have
to check the return value of the ob.__eq__ function it calls *every
time*. That would slow down the speed of the 99.xx% of cases where the
check is not needed and would still not prevent exceptions. And if the
return value was bad, all operator.eq could do is raise and exception
anyway.
Sure, but then it would be a bug to return a non-boolean from __eq__ and
friends. It is not a bug today. I think that's what Rasmus is proposing.
--
Robert Kern
"I have come to believe that the whole world is an enigma, a harmless enigma
that is made terrible by our own mad attempt to interpret it as though it had
an underlying truth."
-- Umberto Eco
--
http://mail.python.org/mailman/listinfo/python-list