Python classes:
#!/usr/bin/env python3
import sys
class Student:
# these attributes have default values
firstName = “Alice”
middleName = “Barbara”
lastName = “Clark”
studentId = 12357
year = “Senior”
major = “Computer Science”
gpa = 3.3
def printInfo(self):
print(“Name: ” + self.firstName + ” “, end=””)
print(self.middleName + ” “, end=””)
print(self.lastName)
print(“Student ID: ” + str(self.studentId))
print(“Year: ” + self.year)
print(“Major: ” + self.major)
print(“GPA: ” + str(self.gpa))
def main():
student1 = Student()
student1.firstName = “Albert”
student1.middleName = “Bob”
student1.lastName = “Cooper”
student1.studentId = 12359
student1.year = “Freshman”
student1.gpa = 3.1
student1.printInfo()
student2 = Student()
student2.printInfo()
if __name__ == ‘__main__’:
try:
main()
except KeyboardInterrupt:
print(“\nQuitting. Goodbye.”)
sys.exit()
Of course, the above code is inefficient, but I only wanted to demonstrate the basics of a class. You can have a class with attributes and methods. In this case, the above class has no constructor that accepts arguments, so you can only modify the instance variables using assignment and accessing the properties of an object. The better solution is to use constructors so that all of that stuff can be changed when the object is instantiated.
The above class has default values, which are not really necessary if you use a constructor properly. However, for some optional attributes, such as middle name, you might want to give the argument a default value in the constructor, as shown below.
Python constructors:
#!/usr/bin/env python3
import sys
class Student:
def __init__(self, first, last, sid, year, major, gpa, middle=””):
self.firstName = first
self.middleName = middle
self.lastName = last
self.studentId = sid
self.year = year
self.major = major
self.gpa = gpa
def printInfo(self):
print(“Name: ” + self.firstName + ” “, end=””)
if self.middleName != “”:
print(self.middleName + ” “, end=””)
print(self.lastName)
print(“Student ID: ” + str(self.studentId))
print(“Year: ” + self.year)
print(“Major: ” + self.major)
print(“GPA: ” + str(self.gpa))
def main():
student1 = Student(“Michael”, “Anderson”, 123460,
“Sophomore”, “Mathematics”, 3.4)
student1.printInfo()
if __name__ == ‘__main__’:
try:
main()
except KeyboardInterrupt:
print(“\nQuitting. Goodbye.”)
sys.exit()
Python inheritance:
class GradStudent(Student):
def __init__(self, first, last, sid, year, major, gpa,
thesis, isFullTime, greScores, gradMajor,
middle=””, specialization=””):
Student.__init__(self, first, last, sid, year, major, gpa, middle)
self.thesis = thesis
self.isFullTime = isFullTime
self.greScores = greScores
self.gradMajor = gradMajor
self.specialization = specialization
def main():
student1 = Student(“Michael”, “Anderson”, 123460,
“Sophomore”, “Mathematics”, 3.4)
student1.printInfo()
student2 = GradStudent(“Melissa”, “Adams”, 123789,
“5th”, “Computer Science”,
3.5, “using neural networks for infosec”,
False, [165, 163, 4.5], “Computer Science”,
“Chelsea”, “Cybersecurity”)
student2.printInfo()
The above example allows the GradStudent subclass to use the constructor and printInfo() method of the Student class. However, even with all the new attributes, the printInfo() method only prints out the properties that are in the Student superclass, meaning many useful pieces of information are missing.
The solution here is to override the printInfo() method.
Python polymorphism/overriding:
In Python, you simply redefine a method in order to override it. Unlike Java, there is no need for something like @Override before it.
Notice how the GradStudent subclass uses polymorphism for the printInfo() method. It looks very simple, but it allows for things like having an array of Student objects, some elements of which are GradStudents, and you can still do something like studentArray[x].printInfo() no matter what kind of student they are, but they will all have their own subclass implementations of the method.
#!/usr/bin/env python3
import sys
class Student:
def __init__(self, first, last, sid, year, major, gpa, middle=””):
self.firstName = first
self.middleName = middle
self.lastName = last
self.studentId = sid
self.year = year
self.major = major
self.gpa = gpa
def printInfo(self):
print(“Name: ” + self.firstName + ” “, end=””)
if self.middleName != “”:
print(self.middleName + ” “, end=””)
print(self.lastName)
print(“Student ID: ” + str(self.studentId))
print(“Year: ” + self.year)
print(“Major: ” + self.major)
print(“GPA: ” + str(self.gpa))
class GradStudent(Student):
def __init__(self, first, last, sid, year, major, gpa,
thesis, isFullTime, greScores, gradMajor,
middle=””, specialization=””):
Student.__init__(self, first, last, sid, year, major, gpa, middle)
self.thesis = thesis
self.isFullTime = isFullTime
self.greScores = greScores
self.gradMajor = gradMajor
self.specialization = specialization
def printInfo(self):
print(“Name: ” + self.firstName + ” “, end=””)
if self.middleName != “”:
print(self.middleName + ” “, end=””)
print(self.lastName)
if self.isFullTime:
print(“Full time “, end=””)
else:
print(“Part time “, end=””)
print(“graduate student”)
print(“Student ID: ” + str(self.studentId))
print(“Year: ” + self.year)
print(“Undergrad major: ” + self.major)
print(“Grad school major: ” + self.gradMajor)
print(“Specialization: ” + self.specialization)
print(“GPA: ” + str(self.gpa))
print(“Thesis: ” + self.thesis)
print(“GRE scores: “)
print(“Verbal reasoning: ” + str(self.greScores[0]))
print(“Quantitative reasoning: ” + str(self.greScores[1]))
print(“Analytical writing: ” + str(self.greScores[2]))
def main():
studentList = []
studentList.append(Student(“Michael”, “Anderson”, 123460,
“Sophomore”, “Mathematics”, 3.4))
studentList.append(GradStudent(“Melissa”, “Adams”, 123789,
“5th”, “Computer Science”,
3.5, “using neural networks for infosec”,
False, [165, 163, 4.5], “Computer Science”,
“Chelsea”, “Cybersecurity”))
for student in studentList:
student.printInfo()
# in the above line, there are two classes
# (Student and GradStudent)
# with different printInfo() methods,
# but they can both be called the same way
# this is what polymorphism is all about
if __name__ == ‘__main__’:
try:
main()
except KeyboardInterrupt:
print(“\nQuitting. Goodbye.”)
sys.exit()
Abstract classes in Python:
from abc import *
class Student(ABC):
def __init__(self, first, last, sid, year, major, gpa, middle=””):
self.firstName = first
self.middleName = middle
self.lastName = last
self.studentId = sid
self.year = year
self.major = major
self.gpa = gpa
@abstractmethod
def printInfo(self):
print(“Name: ” + self.firstName + ” “, end=””)
if self.middleName != “”:
print(self.middleName + ” “, end=””)
print(self.lastName)
print(“Student ID: ” + str(self.studentId))
print(“Year: ” + self.year)
print(“Major: ” + self.major)
print(“GPA: ” + str(self.gpa))
In the above example, the Student class is now an abstract class (because it extends ABC, which stands for Abstract Base Class). This means only subclasses of the abstract base class, such as GradStudent, can be instantiated. All abstract methods (designated with @abstractmethod) must be implemented. In this case, the only one the subclass needs to implement is printInfo(). Abstract classes are not suitable for all situations.
Creating objects in Python (there is no βnewβ keyword):
someObject = someClass(arg1, arg2, arg3)