why defining only __lt__ makes > operation possible?

Question:

class Node:
    def __init__(self,a,b):
        self._a=a
        self._b=b
    def __lt__(self,other):
        return self._a<other._a


a=Node(1,2)
b=Node(0,4)
print(a>b)

The code above shows True.

class Node:
    def __init__(self,a,b):
        self._a=a
        self._b=b
    def __lt__(self,other):
        return self._a<other._a
    def __eq__(self,other):
        return self._a==other._a

a=Node(1,2)
b=Node(0,4)
print(a>=b)

The code above shows TypeError: ‘<=’ not supported between instances of ‘Node’ and ‘Node.

Why defining only lt makes >(which is gt) operation possible?
why defining both lt and eq makes <= impossible?

Asked By: dollydollydon

||

Answers:

The Python docs dictates:

There are no swapped-argument versions of these methods (to be used when the left argument does not support the operation but the right argument does); rather, __lt__() and __gt__() are each other’s reflection, __le__() and __ge__() are each other’s reflection, and __eq__() and __ne__() are their own reflection.

So if the left-hand-side argument doesn’t implement a comparison operator while the right-hand-side implements its reflection, that reflection is called instead. This also explains why Python doesn’t combine __lt__() and __eq__() into __le__() — it simply isn’t considered.

Answered By: iBug

In the first example you are comparing with >, which uses __gt__. In the second example you are comparing with >=, which is a different comparison, and it uses __ge__.

Have a look at rich comparison at the docs

These are the so-called “rich comparison” methods. The correspondence
between operator symbols and method names is as follows: x<y calls
x.__lt__(y), x<=y calls x.__le__(y), x==y calls x.__eq__(y), x!=y
calls x.__ne__(y), x>y calls x.__gt__(y), and x>=y calls x.__ge__(y).

Answered By: Guy
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.