Antoon Pardon wrote: > It would be better if cmp would give an indication it > can't compare two objects instead of giving incorrect > and inconsistent results.
If two objects aren't totally comparable, then using 'cmp' on them is ill-defined to begin with. The Standard Thing To Do is throw an exception; see the Highly Obscure Case of the Complex Numbers. >>>1 == 1j False >>>1 != 1j True >>>1 < 1j Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: cannot compare complex numbers using <, <=, >, >= >>>cmp(1j,1j) 0 >>>cmp(1,1j) Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: cannot compare complex numbers using <, <=, >, >= So using the well-known case of complex numbers, the semantics are already well-defined. >>> class Incomparable: ... def __cmp__(self,other): ... raise TypeError("cannot compare Incomparables using <, <=, >, >=") ... def __eq__(self,other): ... return self is other ... def __neq__(self,other): ... return self is not other >>> a1 = Incomparable() >>> a2 = Incomparable() >>> a1 == a1 1 # I'm running on python 2.2.3 at the moment, so hence the 1. >>> a2 == a2 1 >>> a1 == a2 0 >>> a1 < a2 Traceback (most recent call last): File "<stdin>", line 1, in ? File "<stdin>", line 3, in __cmp__ TypeError: cannot compare Incomparables using <, <=, >, >= >>> cmp(a1,a2) Traceback (most recent call last): File "<stdin>", line 1, in ? File "<stdin>", line 3, in __cmp__ TypeError: cannot compare Incomparables using <, <=, >, >= So your use-case is already well-defined, and rather simple. Make __cmp__ raise an exception of your choice, and define rich comparators only for the comparisons that are supported. If, as you say in another post, "some" pairs in D cross D are comparable on an operator but not all of them (and further that this graph is not transitive), then your _ONLY_ choices, no matter your implementation, is to return some possibly inconsistent result (a < b == 1, b < c == 1, a < c == 0) or raise an exception for unapplicable comparisons. This isn't a Python problem; this is a problem from formal mathematics. Personally, I'd favor the "raise an exception" case, which is exactly what will happen if you define rich comparisons and let cmp throw an exception. Operators that assume comparable objects, like sort, also almost always assume a total order -- inconsistent operations can give weird results, while throwing an exception will at least (usually) give some sort of error that can be caught. Another poster mentioned the B-tree example, and that isn't solvable in this case -- B-trees assume a total order, but by their nature aren't explicit about checking for it; inserting a "partial plus exception" order might result in tree failure at weird times. An inconsistent order, however, is even worse -- it would corrupt the tree at the same times. -- http://mail.python.org/mailman/listinfo/python-list