2

I have seen similar questions, but they did not answer why python __lt__ has higher priority than __gt__?

Quick example, let me give a superclass and a subclass:

class Person(object):
    id = 0
    def __init__(self, name):
        self.name = name
        self.id = Person.id
        Person.id += 1

    def __str__(self):
        return self.name

    def __lt__(self, other):
        return self.id < other.id

class SubPerson(Person):
    def __gt__(self, other):
        return self.name > other.name

Here in superclass Person, I created a __lt__ method, to compare based on Person's self.id. In sub class SubPerson, I created a __gt__ method to compare based on the self.name.

What I found is that if I created a number of SubPerson instances in a list:

s1 = SubPerson('WWW'); s1.id = 14
s2 = SubPerson('XXX'); s2.id = 12
s3 = SubPerson('YYY'); s3.id = 11
s4 = SubPerson('ZZZ'); s4.id = 13
lst2 = [s2, s1, s4, s3]
lst2.sort()
print([i.__str__() for i in lst2])  # >>> ['YYY', 'XXX', 'ZZZ', 'WWW']

What I found is that: if __lt__ is defined in superclass, then even if you define __gt__ in subclass, it will still sort by the __lt__ method in superclass

But if it is the other way around, define __gt__ in superclass and __lt__ in subclass, then it will then sort by __lt__ in subclass

If the two method names are the same (both lt or both gt), obviously, the subclass will override superclass, as it should be.

But it seems when they are different, it follows a different rule: by whatever __lt__ defines. I've also noticed that even if in one class, if both __lt__ and __gt__ are defined (based on different things, it will still sort by __lt__ method)

SO back to my question, is my observation true or not? and since I am a beginner, and I have not read through the whole python documents, can somebody point me out where in the documents that this rule is written.

6
  • 2
    See the documentation: “This method sorts the list in place, using only < comparisons between items.” Commented Jan 18, 2018 at 3:22
  • @Ryan but it seems that it will still sort if I only define __gt__ method?? Commented Jan 18, 2018 at 3:24
  • 1
    @Code_Control_jxie0755: You defined both; the subclass still inherited __lt__ from the parent. Commented Jan 18, 2018 at 3:27
  • @ShadowRanger I mean, I can go back and delete the __lt__ in the parent, and sub will then sort by __gt__. Commented Jan 18, 2018 at 3:29
  • 3
    @Code_Control_jxie0755: See user2357112's answer; there is a reflective test applied (checking the right hand side's reversed comparison, __gt__) when the left hand side doesn't support the direct (__lt__) comparison. You benefit by accident. In practice, you should really only define __eq__ and __lt__, then decorate the class with functools.total_ordering to define the other comparisons in terms of them. Commented Jan 18, 2018 at 3:31

1 Answer 1

8

list.sort uses only < comparisons. This is documented.

Binary operators like < will try the left-hand operand's method first unless the right-hand operand's class is a subclass of the left-hand operand's class. The other operand's method will only be considered if the first method is missing or returns NotImplemented. The left-hand operand's method for < is __lt__, and the right-hand operand's method is __gt__. This is also documented.

Since all your list elements have the same class and __lt__ always succeeds, only the __lt__ methods end up getting called.

Sign up to request clarification or add additional context in comments.

3 Comments

But I noticed that if I only define __gt__ method, it will still sort? So in a way, __lt__ is not the must have????
I don't have to define __lt__ to make .sort() work, I can delete all the __lt__ and leave only __gt__ it will still sort
@Code_Control_jxie0755 I think your question about why gt works is answered in the answer itself - it took me a sec to understood too: "The other operand's method will only be considered if the first method is missing or returns NotImplemented." So if lt does not exist, then it reverses the operands and your gt on the righthand operatnd is considered.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.