Previous Lecture Lecture 5 Next Lecture

Lecture 5, Tue 01/21

Operator Overloading, Inheritance

Recorded Lecture: 1_21_25

Operator Overloading

Defining __str__

from Student import Student

s1 = Student("Gaucho", 1234567)
s2 = Student("Jane", 5555555)
print(s1) <Student.Student object at 0x7fd5380d8e80>
def __str__(self):
	''' returns a string representation of a student '''
	return "Student name: {}, perm: {}".format(self.name, self.perm) 

Overriding the ‘+’ operator

def __add__(self, rhs):
	''' Takes two students and returns a list containing these two students '''
    return [self, rhs]
x = s1 + s2 # returns a list of s1 + s2
print(type(x)) # list type

for i in x:
	print(i)

# Output of for loop
# Student name: Gaucho, perm: 1234567
# Student name: Jane, perm: 5555555

Overloading the ‘<=’ and ‘>=’ operator

# <=
def __le__(self, rhs):
	''' Takes two students and returns True if the
		student is less than or equal to the other
		student based on the lexicographical order
		of the name '''
	return self.name.upper() <= rhs.name.upper()

# >=
def __ge__(self, rhs):
	''' Takes two students and returns True if the
		student is greater than or equal to the other
		student based on the lexicographical order
		of the name '''
	return self.name.upper() >= rhs.name.upper()

# >
# def __gt__

# <
# def __lt__
print(s1 <= s2) # True
print(s1 >= s2) # False
print(s1 == s2) # False
print(s1 < s2) # ERROR, we didn’t define the __lt__ method

Inheritance

# Animal.py
class Animal:
	''' Animal class type that contains attributes for all animals '''

def __init__(self, species=None, name=None):
	self.species = species
	self.name = name

def setName(self, name):
	self.name = name

def setSpecies(self, species):
	self.species = species

def getAttributes(self):
	return "Species: {}, Name: {}".format(self.species, self.name)

def getSound(self):
	return "I'm an Animal!!!"
# Cow.py

from Animal import Animal

class Cow(Animal):
    # Available method for the Cow Class 
    def setSound(self, sound):
        self.sound = sound
c = Cow("Cow", "Betsy")
print(c.getAttributes())
c.setSound("Moo") # Sets a Cow sound attribute to "Moo"
print(c.getSound()) # I’m an Animal!!! (calls the Animal.getSound method)
# in Cow class
def getSound(self):
	return "{}!".format(self.sound)
c = Cow("Cow", "Betsy")
c.setSound("Moo") # Sets a Cow sound to "Moo"
print(c.getSound()) # Moo!
a = Animal("Unicorn", "Lala")
print(a.getAttributes())
print(a.getSound()) # I’m an Animal!!!

Note: The constructed object type will dictate which method in which class is called

Extending Superclass Methods

class Cow(Animal):
	def getSound(self):
		s = "Using Super class getSound method\n"
		s += Animal.getSound(self) + "\n" # Uses Animal.getSound method
		s += "Extending it with our own getSound functionality" + "\n"
		s += "{}!!!".format(self.sound)
		return s

# Output:
# Using super class getSound method
# I'm an Animal!!!
# Extending it with our own getSound functionality
# Moo!!!

Extending Constructors in a Child Class

# In Cow.py

    def __init__(self, species=None, name=None, sound=None):
		super().__init__(species, name)
		#Animal.__init__(self, species, name) also works
		self.sound = sound
c = Cow("Cow", "Betsy", "Moo") # Passes in data for Animal AND Cow
a = Animal("Unicorn", "Lala")

zoo = [c, a]

for i in zoo:
	print(i.getAttributes())
	print(i.getSound())
	print("---")