Comparisons: __lt__, __gt__, and Others

Our next batch of overloading methods supports comparisons. As suggested in Table 30-1, classes can define methods to catch all six comparison operators: <, >, <=, >=, ==, and !=. These methods are generally straightforward to use, but keep the following qualifications in mind:

We don’t have space for an in-depth exploration of comparison methods, but as a quick introduction, consider the following class and test code:

class C:
    data = 'spam'
    def __gt__(self, other):               # 3.X and 2.X version
        return self.data > other
    def __lt__(self, other):
        return self.data < other

X = C()
print(X > 'ham')                           # True  (runs __gt__)
print(X < 'ham')                           # False (runs __lt__)

When run under Python 3.X or 2.X, the prints at the end display the expected results noted in their comments, because the class’s methods intercept and implement comparison expressions. Consult Python’s manuals and other reference resources for more details in this category; for example, __lt__ is used for sorts in Python3.X, and as for binary expression operators, these methods can also return NotImplemented for unsupported arguments.

The __cmp__ Method in Python 2.X

In Python 2.X only, the __cmp__ method is used as a fallback if more specific methods are not defined: its integer result is used to evaluate the operator being run. The following produces the same result as the prior section’s code under 2.X, for example, but fails in 3.X because __cmp__ is no longer used:

class C:
    data = 'spam'                          # 2.X only
    def __cmp__(self, other):              # __cmp__ not used in 3.X
        return cmp(self.data, other)       # cmp not defined in 3.X

X = C()
print(X > 'ham')                           # True  (runs __cmp__)
print(X < 'ham')                           # False (runs __cmp__)

Notice that this fails in 3.X because __cmp__ is no longer special, not because the cmp built-in function is no longer present. If we change the prior class to the following to try to simulate the cmp call, the code still works in 2.X but fails in 3.X:

class C:
    data = 'spam'
    def __cmp__(self, other):
        return (self.data > other) - (self.data < other)

So why, you might be asking, did I just show you a comparison method that is no longer supported in 3.X? While it would be easier to erase history entirely, this book is designed to support both 2.X and 3.X readers. Because __cmp__ may appear in code 2.X readers must reuse or maintain, it’s fair game in this book. Moreover, __cmp__ was removed more abruptly than the __getslice__ method described earlier, and so may endure longer. If you use 3.X, though, or care about running your code under 3.X in the future, don’t use __cmp__ anymore: use the more specific comparison methods instead.