Inconsistency in Python's Comparisons

Tim Peters at
Wed Mar 17 04:54:53 CET 2004

[Dietrich Epp]
> Without invoking double-underscore black magic, it is possible to
> choose a, b, and c in Python such that:
> a < b
> b < c
> c < a


> This could cause sorting functions to malfunction.

In what sense?  The builtin list.sort() doesn't depend on comparisons being
sane, because user-defined comparisons can display arbitrarily goofy
behavior.  All list.sort() promises then is that it won't blow up, and that
the list at the end will contain some permutation of its input state (no
element will be lost or duplicated).  As to which permutation, garbage-in
garbage-out rules if the elements don't enjoy a total ordering.

[example with str < instance of class whose name starts with "t" <
                    unicode < str]

Took you a while, didn't it <wink>?

> Possible kludge fix: Change default_3way_compare() to use "basestring"
> as the typename for both built-in string types.
> Possible elegant fix: Any class whose members may either be less than
> or greater than members of a different class, which often share a
> common superclass, use the name of the superclass for comparisons with
> objects of incompatible types.  This parallels the comparison of
> numeric types because they compare as if their type name were empty.

They didn't always.  In the very early days, e.g.,

    3 < [3] < 2L < 3

was true (3 < [3] because "int" < "list", and [3] < 2L because "list" <
"long" -- the same trick you played to pick a class name alphabetically
between "str" and "unicode").  Using an empty string as a numeric type name
was a gross hack to stop that kind of example.

If you'd like to work up a patch, I expect it would be accepted.  In the
mythical Python 3.0, I expect the default mixed-type comparison rule will be
to return False if the relation is "==", True if "!=", and to raise
TypeError otherwise.

More information about the Python-list mailing list