python total_ordering : why __lt__ and __eq__ instead of __le__?
The documentation states you must define one of __lt__()
, __le__()
, __gt__()
, or __ge__()
, but only should supply an __eq__()
method.
In other words, the __eq__
method is optional.
The total_ordering
implementation does not require you to specify an __eq__
method; it only tests for the __lt__()
, __le__()
, __gt__()
, or __ge__()
methods. It supplies up to 3 missing special methods based of one of those 4.
You can't base the order on just __le__
or __ge__
because you can't assume that you can swap a
and b
; if b
is a different type b.__le__
might not be implemented and so your a < b <=> not (b <= a)
map can't be guaranteed. The implementation uses (a <= b) and (a != b)
if __le__
is not defined but __lt__
has been.
The full table of mappings is:
comparison | available | alternative |
---|---|---|
a > b | a < b | (not a < b) and (a != b) |
a <= b | (not a <= b) | |
a >= b | (a >= b) and (a != b) | |
a <= b | a < b | (a < b) or (a == b) |
a > b | (not a > b) | |
a >= b | (not a >= b) or (a == b) | |
a < b | a <= b | (a <= b) and (a != b) |
a > b | (not a > b) and (a != b) | |
a >= b | (not a >= b) | |
a >= b | a < b | (not a < b) |
a <= b | (not a <= b) or (a == b) | |
a > b | (a > b) or (a == b) |
The __eq__
method is optional because the base object
object defines one for you; two instances are considered equal only if they are the same object; ob1 == ob2
only if ob1 is ob2
is True
. See the do_richcompare()
function in object.c
; remember that the ==
operator in the code there is comparing pointers.