Classes and objects solution
Question 1
Write a definition for Student class
Define __init__(self, marks=[]) for the Student class
Define add_marks(self,lst) that appends mark to the marks list
Create two students, s1 and s2.
Add [25,45,65] to s1
Print marks of s1 and s2
Observe what happens?
Fix the code.
Initial Implementationclass Student:
def __init__(self, marks=[]):
self.marks = marks
def add_marks(self,lst):
self.marks.extend(lst)
s1= Student()
s2=Student()
s1.add_marks([25,45,65])
print('Contents of s1',s1.marks)
print('Contents of s2',s2.marks)
Output:
Contents of s1 [25, 45, 65]
Contents of s2 [25, 45, 65]
Observation:
list is getting added to s1, but s2 also shows the same contents. What is expected is an empty list for s2 but s1 consisting of [25,45,65]
Why this happens?
https://stackoverflow.com/questions/4841782/python-constructor-and-default-value
Solution:
def __init__(self, marks=None):
if marks==None:
self.marks=[]
else:
self.marks = marks
Output:
Contents of s1 [25, 45, 65]
Contents of s2 []
Question 2
For all classes include __init__ and __str__
Write a program that has a class called Person.
- Attributes of person class : usn, name,dob, gender
- Inside __init__
- Validate USN (1CR15CS104) before setting the private value usn
- Validate date by trying to create a valid date object from the string.
- If date is valid, calculate age and store it in the age instance variable.
** use assert or exceptions to display unsuccessful object creations.
- Write a method called time_to_bday() that returns the days to the Persons next b’day. Use the date, timedelta.
Inherit a class Student from Person which also has a class MarksAttendance
- Attributes for student class : branch, year, MA
- __init__ should receive (usn, name, dob, gender, branch, year, ma)
- Should call super().__init__ to initialize usn, name, dob and gender
- Should initialize year, branch and ma
- ma is an object of the MarksAttendance class
- __str__ should return a printable student class with all the details
MarksAttendance class
- Class Attribute : max_mark:80, max_classes:62
- Attributes : marks, attendance, marks_dict, att_dict
- __init__ should receive a list of subjects, list of marks and list of attendance
- Validate that lengths of al 3 lists are equal
- Create a dictionary object for marks_dict, assigning marks to subjects
- Create a dictionary object for att_dict, assigning attendance to subject
- Calculate marks and attendance by calling methods
- __str__ should return a printable student class with all the details
- Calculate and return average marks by using the class attribute max_marks
- Calculate and return average percentage by using class attribute max_classes
Discussion based on submissions:
When checking USN of a form 1CR15CS003 some use \w... to check for the alpha characters, but remember \w includes underscore so use [a-zA-Z] or convert the usn to uppercase and then use[A-Z] in RE.
FYI VTU has 4 region codes (http://www.vtuboss.in/2017/11/vtu-college-codes-of.html)
This USN format can be matched at the start only
so re.match([1-4][A-Z]{2}[0-9][A-Z]{2}[0-9]{3}, usn.upper())
and you don't need to check if length of usn is lesser than 10
so,
if len(usn)==10 and and re.match([1-4][A-Z]{2}[0-9][A-Z]{2}[0-9]{3}, usn.upper())
and you don't need to check if length of usn is lesser than 10
so,
if len(usn)==10 and and re.match([1-4][A-Z]{2}[0-9][A-Z]{2}[0-9]{3}, usn.upper())
Program:
from datetime import date
import re
class Person:
def __init__(self, usn='', name='', dob=None, gender=''):
if self.validate_usn(usn) and self.validate_date(dob):
self.usn=usn
self.dob=dob
else:
""" Object creation should fail with appropriate error msg"""
print("Invalid usn or dob, eg. 1CR12CS001, 1990-11-04")
exit()
self.name = name
self.gender = gender
self.age = self.calculate_age()
def __str__(self):
""" should return in the form, 1CR14CS015 Arjun 1990-11-2 M """
return self.usn+' '+self.name+' '+self.dob+' '+self.gender
def validate_usn(self,usn):
""" use regular expression to validate usn of form 1CR14CS015 """
if re.match('[0-9][A-Z][A-Z][0-9][0-9][A-Z][A-Z][0-9]{3}',usn):
return True
else: return False
def validate_date(self, dob):
""" create a date object """
t = dob.split('-')
try:
d = date(int(t[0]),int(t[1]),int(t[2]))
return True
except:
return False
def calculate_age(self):
""" calculate and extract from timedelta object or by calculating difference between years"""
pass
def get_age(self):
t = self.dob.split('-')
""" return age """
today = date.today()
bday_year = int(t[0])
bday_month=int(t[1]) crossed= bday_month<today.month # True: 1 False: 0 return today.year - bday_year - crossed def time_to_bday(self): """ get today from the date module use a variable bday_this_year and set year of b'day to current year. if today is <= bday_this_year calculate the time difference between today and dob, extract days from timedelta if today is past, then set year in bday_this_year to next year and calculate return time delta object """ today = date.today() t=self.dob.split('-') b_day_this_year = date(today.year, int(t[1]),int(t[2])) if today <=b_day_this_year: return(b_day_this_year-today).days else: b_day_next_year = date(today.year+1,int(t[1]),int(t[2])) return(b_day_next_year-today).days class MA: max_marks = 80 # for each subject max_classes = 62 # for each class def __init__(self, subject_list, marks_list, att_list): if len(subject_list)==len(marks_list)==len(att_list): self.marks_dict={} self.att_dict={} i = 0 for subject in subject_list: self.marks_dict[subject] = marks_list[i] self.att_dict[subject]=att_list[i] i+=1 self.marks = self.calculate_avg_marks() self.att = self.calculate_avg_att() def __str__(self): """ return in the form for each subject, subjectname : marks - 85%, attendance - 95%""" st='\n' for subject in self.marks_dict.keys(): st+=subject+" : marks - "+str(self.marks_dict[subject])+",attendance - "+str(self.att_dict[subject])+"\n" s = '\nOverall Marks percentage: %0.2f %%\nOverall Attendance percentage: %0.2f %%\n'%(self.marks, self.att) print(s) st+=s return st def calculate_avg_marks(self): marks = self.marks_dict.values() total =sum(marks) num_subs = len(marks) return (total/(num_subs*self.max_marks))*100 def calculate_avg_att(self): att = self.att_dict.values() total =sum(att) num_subs = len(att) return (total/(num_subs* self.max_classes))*100 class Student(Person): def __init__(self, usn, name, dob, gender, branch, year, ma): super().__init__(usn,name,dob, gender) self.branch = branch self.year = year def __str__(self): """ combine string representations of Person oject with student object and ma object and return all details of a student in printable string version """ return super().__str__()+ma.__str__() #Driver Code subject_lst = ['OS', 'SSCD', 'PAP', 'CG'] marks_lst = [65,60,55,50] att_lst = [42,50,60,58] ma = MA(subject_lst, marks_lst, att_lst) s = Student('1CR14CS015', 'Arjun', '1990-02-04', 'M', 'CSE',4, ma) print(s) print("Age", s.get_age()) print("Time to next birthday %d days" % s.time_to_bday())
bday_month=int(t[1]) crossed= bday_month<today.month # True: 1 False: 0 return today.year - bday_year - crossed def time_to_bday(self): """ get today from the date module use a variable bday_this_year and set year of b'day to current year. if today is <= bday_this_year calculate the time difference between today and dob, extract days from timedelta if today is past, then set year in bday_this_year to next year and calculate return time delta object """ today = date.today() t=self.dob.split('-') b_day_this_year = date(today.year, int(t[1]),int(t[2])) if today <=b_day_this_year: return(b_day_this_year-today).days else: b_day_next_year = date(today.year+1,int(t[1]),int(t[2])) return(b_day_next_year-today).days class MA: max_marks = 80 # for each subject max_classes = 62 # for each class def __init__(self, subject_list, marks_list, att_list): if len(subject_list)==len(marks_list)==len(att_list): self.marks_dict={} self.att_dict={} i = 0 for subject in subject_list: self.marks_dict[subject] = marks_list[i] self.att_dict[subject]=att_list[i] i+=1 self.marks = self.calculate_avg_marks() self.att = self.calculate_avg_att() def __str__(self): """ return in the form for each subject, subjectname : marks - 85%, attendance - 95%""" st='\n' for subject in self.marks_dict.keys(): st+=subject+" : marks - "+str(self.marks_dict[subject])+",attendance - "+str(self.att_dict[subject])+"\n" s = '\nOverall Marks percentage: %0.2f %%\nOverall Attendance percentage: %0.2f %%\n'%(self.marks, self.att) print(s) st+=s return st def calculate_avg_marks(self): marks = self.marks_dict.values() total =sum(marks) num_subs = len(marks) return (total/(num_subs*self.max_marks))*100 def calculate_avg_att(self): att = self.att_dict.values() total =sum(att) num_subs = len(att) return (total/(num_subs* self.max_classes))*100 class Student(Person): def __init__(self, usn, name, dob, gender, branch, year, ma): super().__init__(usn,name,dob, gender) self.branch = branch self.year = year def __str__(self): """ combine string representations of Person oject with student object and ma object and return all details of a student in printable string version """ return super().__str__()+ma.__str__() #Driver Code subject_lst = ['OS', 'SSCD', 'PAP', 'CG'] marks_lst = [65,60,55,50] att_lst = [42,50,60,58] ma = MA(subject_lst, marks_lst, att_lst) s = Student('1CR14CS015', 'Arjun', '1990-02-04', 'M', 'CSE',4, ma) print(s) print("Age", s.get_age()) print("Time to next birthday %d days" % s.time_to_bday())
Output:
Overall Marks percentage: 71.88
Overall Attendance percentage: 84.68
1CR14CS015 Arjun 1990-11-04 M
OS : marks - 65,attendance - 42
SSCD : marks - 60,attendance - 50
PAP : marks - 55,attendance - 60
CG : marks - 50,attendance - 58
Overall Marks percentage: 71.88 %
Overall Attendance percentage: 84.68 %
Age -29
Time to next birthday 163 days
Ensure your messages are getting displayed if you feed the wrong format or USN.
Comments
Post a Comment