Annoying behaviour of the != operator

Dan Sommers me at privacy.net
Fri Jun 10 13:51:24 EDT 2005


On Fri, 10 Jun 2005 09:50:56 -0500,
Rocco Moretti <roccomoretti at hotpop.com> wrote:

> Dan Sommers wrote:
>> On Thu, 09 Jun 2005 15:50:42 +1200,
>> Greg Ewing <greg at cosc.canterbury.ac.nz> wrote:
>> 
>>> Rocco Moretti wrote:
>>> 
>>>> The main problem is that Python is trying to stick at least three
>>>> different concepts onto the same set of operators: equivalence (are
>>>> these two objects the same?), ordering (in a sorted list, which comes
>>>> first?), and mathematical "size".
>> 
>>>> This gives the wacky world where
>>>> "[(1,2), (3,4)].sort()" works, whereas "[1+2j, 3+4j].sort()" doesn't.
>> Python inherits that wackiness directly from (often wacky) world of
>> Mathematics.
>> IMO, the true wackiness is that
>> [ AssertionError, (vars, unicode), __name__, apply ].sort( )
>> "works," too.  Python refusing to sort my list of complex numbers is a
>> Good Thing.

> The "wackyness" I refered to wasn't that a list of complex numbers isn't
> sortable, but the inconsistent behaviour of list sorting. As you
> mentioned, an arbitraty collection of objects in a list is sortable, but
> as soon as you throw a complex number in there, you get an exception.

Yes, I agree:  it is inconsistent.

> One way to handle that is to refuse to sort anything that doesn't have
> a "natural" order. But as I understand it, Guido decided that being
> able to sort arbitrary lists is a feature, not a bug. But you can't
> sort ones with complex numbers in them, because you also want
> '1+3j<3+1j' to raise an error.

As George Sakkis noted, Guido has since recanted.  Unfortunately, in
this case, the time machine would have broken too much existing code.

>> Four separate classes of __comparison__ methods in a language that
>> doesn't (and can't and shouldn't) preclude or warn about rules
>> regarding which methods "conflict" with which other methods?  I do
>> not claim to be an expert, but that doesn't seem very Pythonic to me.

> What "conflict"? Where are you getting the doesn't/can't/shouldn't
> prescription from?

Perhaps "conflict" wasn't quite the right word.  For example, if I
define __ne__ and __equal__ and __lt__, then which method(s) should
Python use if I later use a <= or a >= operator?

"Doesn't" and "can't" (call me pessimistic) comes from all the issues
and disagreements we're having in this thread, and "shouldn't" comes
from the Zen:

    Explicit is better than implicit.
    In the face of ambiguity, refuse the temptation to guess.

> Which method you use depends on what you want to achieve:

> (Hypothetical Scheme)
> Object Identity? - use 'is'
> Mathematical Ordering? - use '__eq__' & friends
> Object Equivalence? - use '__equiv__'
> Arbitrary Ordering? (e.g. for list sorting) - use '__order__'

So which method would python use when sorting a list that happens to
consist only of numbers? or a list that contains mostly integers and a
few complex numbers?

> The only caveat is to define sensible defaults for the cases where one
> fuction is not defined. But that shouldn't be too hard.

At the risk of repeating myself:

    Explicit is better than implicit.
    In the face of ambiguity, refuse the temptation to guess.

Also, as I noted in a previous discussion on an unrelated topic, it
seems that we all have our own notions and limitations of expliciticity
and impliciticity.

> __eqiv__ -> __eq__ -> is
> __order__ -> __lt__/__cmp__

>> AIUI, __cmp__ exists for backwards compatibility, and __eq__ and friends
>> are flexible enough to cover any possible comparison scheme.

> Except if you want the situation where "[1+2j, 3+4j].sort()" works, and
> '1+3j < 3+1j' fails.

I'm sticking with my position that both should fail, unless you
*explicity* tell sort what to do (since for now, we all seem to agree
that the other one should fail).  If I have an application that thinks
it has to sort a list of arbitrary objects, then I have to be clever
enough to help.

> I think the issue is you thinking along the lines of Mathematical
> numbers, where the four different comparisons colapse to one. Object
> identity? There is only one 'two' - heck, in pure mathematics, there
> isn't even a 'float two'/'int two' difference. Equivalence *is*
> mathematical equality, and the "arbitrary ordering" is easily defined
> as "true" ordering. It's only when you break away from mathematics do
> you see the divergance in behavior.

IIRC, there was a discussion about overhauling of all of Python's
numbers to make them act more like the mathematical entities that they
represent rather than the Python objects that they are.  The long/int
"consolidation," better handling of integer division, and the Decimal
class came out of that discussion.  But that still leaves the issue of
what to do with 1 < "foo" and "bar" > 2j and 3j < 4j.

Regards,
Dan

-- 
Dan Sommers
<http://www.tombstonezero.net/dan/>



More information about the Python-list mailing list