Rich comparison methods are used for comparing object instances. It assigns special methods to each operator as given in below table.
Operator | Method |
---|---|
== | __eq__(self, other) |
!= | __ne__(self, other) |
< | __lt__(self, other) |
<= | __le__(self, other) |
> | __gt__(self, other) |
>= | __ge__(self, other) |
The correspondence between operator symbols and method names is as follows: x < y calls x.__lt__(y), x>=y calls x.__ge__(y), and so on. These method may return the singleton NotImplemented if it does not implement the operation for a given pair of arguments. For a successful comparison, False and True should be returned. But, these methods can return any value. If the comparison operator is used in a Boolean context (e.g., in the condition of an if statement), Python will call bool() on the value to determine if the result is true or false.
_hash_() Function
It is called by built-in function hash(). It is used for operations on members of hashed collections including set and dict. __hash__() should return an integer. The only required property is that objects which compare equal have the same hash value. Implementation of hashable collections requires that a key’s hash value is immutable (if the object’s hash value changes, it will be in the wrong hash bucket).
If a class does define an __eq__() method it should also define a __hash()__ method. A class that overrides __eq__() and does not define __hash__() will have its __hash__() implicitly set to None
. When the __hash__() method of a class is None, instances of the class will raise an appropriate TypeError when a program attempts to retrieve their hash value.
Sorting Class Instance
__lt__() function is used by sorted() to sort list of class instances in particular order. In the below example, employee list is arranged based on their level.
class Employee(): def __init__(self, fname, lname, level): self.fname = fname self.lname = lname self.level = level # Implement comparison functions def __lt__(self, other): return self.level < other.level def main(): # Employees list employees = [] employees.append(Employee("Hello", "Baker", 5)) employees.append(Employee("John", "Doe", 4)) employees.append(Employee("Jane", "Smith", 6)) employees.append(Employee("Hitlet", "Durden", 5)) # Sort the items emps = sorted(employees) for emp in emps: print(emp.lname) # Output # Doe # Baker # Durden # Smith if __name__ == "__main__": main()
Example
Below example demonstrates the custom implementation of rich comparison operator. Each of these operator uses class attribute for comparing class instance. Employee attribute level
is used to find the comparison result.
class Employee(): def __init__(self, fname, lname, level): self.fname = fname self.lname = lname self.level = level # Implement comparison functions def __ge__(self, other): return self.level >= other.level def __gt__(self, other): return self.level > other.level def __lt__(self, other): return self.level < other.level def __le__(self, other): return self.level <= other.level def __eq__(self, other): return self.level == other.level def main(): # Employees list employees = [] employees.append(Employee("Hello", "Baker", 5)) employees.append(Employee("John", "Doe", 4)) employees.append(Employee("Jane", "Smith", 6)) employees.append(Employee("Hitlet", "Durden", 5)) # Find senior employees print(bool(employees[0] < employees[3])) # Ouput # False if __name__ == "__main__": main()