Comparing objects with operators
A method can return an object, including an object of its own class. And since self is the object itself, a method can return self too. Here heavier compares two parcels and returns the heavier one, whichever it is:
class Parcel:
def __init__(self, label, weight):
self.label = label
self.weight = weight
def __str__(self):
return f"{self.label} ({self.weight} kg)"
def heavier(self, other):
if self.weight > other.weight:
return self
return other
books = Parcel("Books", 12)
pillow = Parcel("Pillow", 2)
print(books.heavier(pillow))
print(pillow.heavier(books))
Books (12 kg)
Books (12 kg)That works, but it would be nicer to compare parcels the way you compare numbers, with > and <. As it is, Python doesn't know how:
class Parcel:
def __init__(self, label, weight):
self.label = label
self.weight = weight
books = Parcel("Books", 12)
pillow = Parcel("Pillow", 2)
print(books > pillow)
Traceback (most recent call last):
File "main.py", line 9, in <module>
print(books > pillow)
^^^^^^^^^^^^^^
TypeError: '>' not supported between instances of 'Parcel' and 'Parcel'Operator overloading
A class can decide what an operator means for its objects. This is called operator overloading. Each operator has a method with a special name, with two underscores on both sides, like __init__ and __str__. When Python meets a > b and a is an object of your class, it calls a.__gt__(b) ("gt" for greater than). The method returns True or False:
class Parcel:
def __init__(self, label, weight):
self.label = label
self.weight = weight
def __str__(self):
return f"{self.label} ({self.weight} kg)"
def __gt__(self, other):
return self.weight > other.weight
def __lt__(self, other):
return self.weight < other.weight
books = Parcel("Books", 12)
pillow = Parcel("Pillow", 2)
lamp = Parcel("Lamp", 5)
print(books > pillow)
print(books < pillow)
parcels = [books, pillow, lamp]
for parcel in sorted(parcels):
print(parcel)
print("Heaviest:", max(parcels))
True
False
Pillow (2 kg)
Lamp (5 kg)
Books (12 kg)
Heaviest: Books (12 kg)You decide what "greater" means. Here it's the weight; for another class it could be a price, a date, or the alphabetical order of names. And there's a bonus: sorted, min and max compare items with < and >, so they work with your objects too, as soon as the class has these methods.
These are the comparison operators and their methods:
| Operator | Meaning | Method |
|---|---|---|
< |
less than | __lt__(self, other) |
> |
greater than | __gt__(self, other) |
<= |
less than or equal to | __le__(self, other) |
>= |
greater than or equal to | __ge__(self, other) |
== |
equal to | __eq__(self, other) |
!= |
not equal to | __ne__(self, other) |
You only need to write the ones that make sense for your class. The next step looks at ==, which works a little differently.