CodingBison

Python allows us to customize the behavior of objects for common operations like addition, subtraction, comparison, etc. Being able to customize basic operators makes objects more expressive in terms of functionality. If you are familiar with object-oriented operator overloading from other programming languages (like C++), you would find this discussion very familiar!

We begin by providing a table that lists some of the operators that can be loaded in Python. The provided list is, by no means, complete. Please refer to your Python manual for additional operators.


Table: Operator Overloading
Operator MethodDescriptionExample
__init__Called after object creationobj = classObj()
__del__Called before object deletiondel obj
__eq__Equality operatorobjA == objB
__gt__Greater than operatorobjA > objB
__lt__Less than operatorobjA < objB
__add__Add to the objectobjA + objB
__sub__Subtract an objectobjA - objB
__mul__Multiply the objectobjA * objB
__div__Divide the objectobjA / objB
__iadd__Increments the objectobjA += objB
__isub__Decrements the objectobjA -= objB
__contains__Check if objB is present in objAobjB in objA
__setitem__Put objB at indx in objAobjA[indx] = objB
__getitem__Get objB stored at indx in objAobjB = objA[indx]
__str__Printing objectprint(obj)
__len__Length property of objectlen(obj)
__and__Binary ANDobjA & objB
__or__Binary ORobjA | objB
__xor__Binary XORobjA ^ objB
__iter__Iterator handleit = iter(objA)
__next__Next value for iterationnext(it)

Next, we present two examples that illustrate operator overloading for some of the commonly used operators. The first example focuses on a simple object and explores comparison operators like less than, greater than, etc. The second example focuses on an object that represents a group of objects -- this allows us to explore list-like properties of indexing, getting the length of the object, and so on.

The first example provides operator overloading for the following operators: __eq__, __gt__, __lt__, __str__, and __del__. The example uses a simple class, bigCat, that models big cats in the wild. The class has four data attributes to capture various information about big cats: name, geographic location, scientific name, and weight of the cat.

In the example (provided below), the __eq__ method checks if two bigCat objects are same. If both objects have the same name and same scientificName, then they are declared equal. The __lt__ and __gt__ methods compare two bigCat objects by comparing their weight attribute. The example also adds a __str__ method; this method returns the string that is printed when we invoke the print function on the object. Lastly, it also customizes the __del__ method.

 class bigCat():
     def __init__(self, name, location, scientificName, weight):
         self.name = name
         self.location = location
         self.scientificName = scientificName
         self.weight = weight
     def __eq__ (self, rhs):
         if ((self.name == rhs.name) and (self.scientificName == rhs.scientificName)):
             return True
         else:
             return False
     def __gt__ (self, rhs):
         if (self.weight > rhs.weight):
             return True
         else:
             return False
     def __lt__ (self, rhs):
         if (self.weight < rhs.weight):
             return True
         else:
             return False
     def __str__ (self):
         varStr = "Name: " + str(self.name)
         varStr += ", Weight: " + str(self.weight)
         varStr += ", Location: " + str(self.location)
         varStr += ", Scientific Name: " + str(self.scientificName)
         return varStr 
     def __del__ (self):
         print("Deleting this object (name: %s)" % (self.name))

 if __name__ == "__main__":
     objBigCat1 = bigCat("Leopard", "South Africa", "Panthera pardus", 180)
     objBigCat2 = bigCat("Leopard", "China", "Panthera pardus", 200)

     #Test the __str__ method
     print(objBigCat1)
     print(objBigCat2)

     #Test the __eq__ method
     if (objBigCat1 == objBigCat2):
         print("objBigCat1 and objBigCat2 are same")
     else:
         print("objBigCat1 and objBigCat2 are different")

     #Test the __gt__ method
     if (objBigCat1 > objBigCat2):
         print("objBigCat1 is bigger than objBigCat2")
     else:
         print("objBigCat2 is bigger than objBigCat1")

     #Test the __lt__ method
     if (objBigCat1 < objBigCat2):
         print("objBigCat1 is smaller than objBigCat2")
     else:
         print("objBigCat2 is smaller than objBigCat1")

     #Test the __del__ method
     del objBigCat1
     del objBigCat2

We provide the output below. As expected, since objBigCat2 has more weight than objBigCat1, the __lt__ operator confirms that objBigCat1 is less than objBigCat2. Likewise, the __gt__ operator confirms that objBigCat2 is greater than objBigCat1. Also, we add the two del statements towards the end to test the __del__ method. In reality, we can skip that since the objects would get deleted automatically once the program is done.

 Name: Leopard, Weight: 180, Location: South Africa, Scientific Name: Panthera pardus
 Name: Leopard, Weight: 200, Location: China, Scientific Name: Panthera pardus
 objBigCat1 and objBigCat2 are same
 objBigCat2 is bigger than objBigCat1
 objBigCat1 is smaller than objBigCat2
 Deleting this object (name: Leopard)
 Deleting this object (name: Leopard)

We choose the second example such that it represents a collection of objects. This allows us to conveniently test operators like addition, indexing, and length. To be more precise, the example provides overloading for the following operators: __add__, __contains__, __setitem__, __getitem__, and __len__. It also has __str__ and __len__ operators that we saw in the earlier example. The example uses two classes: (a) a "lion" class to hold information about lions and (b) a "pride" class to hold information about a group of lions living together.

In the example, the __add__ method adds a lion object to a list (named "lions") in the pride object. The __contains__ method provides a check to see if a given lion object is present in the list owned by the pride object. It does so by going through all the elements present in the lions list of the objPride; if it finds an element that has the same name and weight, it declares that the passed object exists. The __setitem__ allows us to add an object, once again a lion object, to the pride object at a given index. On the other hand, the __getitem__ method helps us retrieve an object present at the passed index. Next, we customize the __len__ method to return the number of objects present in the lions list of the objPride.

 class lion():
     def __init__(self, name, weight):
         self.name = name
         self.weight = weight
     def __str__ (self):
         varStr = "Name: " + str(self.name)
         varStr += ", Weight: " + str(self.weight)
         return varStr 
     def __del__ (self):
         print("Deleting this object (name: " + self.name + ")")

 class pride():
     def __init__(self):
         self.lions = []
     def __add__ (self, rhs):
         self.lions.append(rhs)
         return self
     def __contains__(self, rhs):
         for elem in self.lions:
             if ((elem.name == rhs.name) and \
                 (elem.weight == rhs.weight)):
                 return True
         return False
     def __setitem__ (self, indx, rhs):
         self.lions[indx] = rhs
     def __getitem__ (self, indx):
         return self.lions[indx]
     def __len__ (self):
         return (len(self.lions))
     def __str__ (self):
         varStr = "\nPrinting the pride:"
         for elem in self.lions:
             varStr += "\nName: " + str(elem.name)
             varStr += ", Weight: " + str(elem.weight)
         return varStr 
     def __del__ (self):
         print("\nDeleting the pride object") 

 if __name__ == "__main__":
     objLion2 = lion("Aslan", 500)
     objLion1 = lion("Mufasa", 400)
     objLion3 = lion("Simba", 20)

     objPride = pride()

     #Test the __add__ method
     objPride = objPride + objLion1
     objPride = objPride + objLion2
     objPride = objPride + objLion3

     #Test the __str__ method
     print(objPride)

     #Test the __len__ method
     print("Total number of lions in the pride are: %d" % (len(objPride)))

     #Test the __contains__ method
     if (objLion3 in objPride):
         print("\nobjLion3 belongs to the objPride")
     else:
         print("\nobjLion3 does not belong to the objPride")

     objLion4 = lion("Nala", 15)
     if (objLion4 in objPride):
         print("\nobjLion4 belongs to the objPride")
     else:
         print("\nobjLion4 does not belong to the objPride")

     #Test the __getitem__ method
     oneLion = objPride[0]
     twoLions = objPride[0:2]
     print("\nPrinting OneLion:")
     print(oneLion)
     print("\nPrinting twoLions:")
     for elem in twoLions:
         print(elem)

     #Test the __settitem__ method
     objPride[0] = objLion4
     print(objPride)

The output (provided below) confirms that we are able to use various list-like operators for our custom class. Here is the output:

 Printing the pride:
 Name: Mufasa, Weight: 400
 Name: Aslan, Weight: 500
 Name: Simba, Weight: 20
 Total number of lions in the pride are: 3

 objLion3 belongs to the objPride

 objLion4 does not belong to the objPride

 Printing OneLion:
 Name: Mufasa, Weight: 400

 Printing twoLions:
 Name: Mufasa, Weight: 400
 Name: Aslan, Weight: 500

 Printing the pride:
 Name: Nala, Weight: 15
 Name: Aslan, Weight: 500
 Name: Simba, Weight: 20

 Deleting the pride object
 Deleting this object (name: Simba)
 Deleting this object (name: Aslan)
 Deleting this object (name: Nala)
 Deleting this object (name: Mufasa)




comments powered by Disqus