In Python3, the functools.total_ordering decorator allows one to only overload __lt__ and __eq__ to get all 6 comparison operators.
I don't get why one has to write two operators when one would be enough, namely __le__ or __ge__, and all others would be defined accordingly :
a < b <=> not (b <= a)
a > b <=> not (a <= b)
a == b <=> (a <= b) and (b <= a)
a != b <=> (a <= b) xor (b <= a)
Is that just because xor operator does not exists natively?
__lt__ is a special method that describes the less-than operator in python. > is a symbol for the less-than operator. It is denoted with a double underscore to represent the special method. This method is not called directly like the less-than operator.
Python Functools – total_ordering() Higher-order functions are dependent functions that call other functions. Total_ordering provides rich class comparison methods that help in comparing classes without explicitly defining a function for it. So, It helps in the redundancy of code.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With