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 Implementation
class 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.

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())

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())

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

Popular posts from this blog

TYL - Food Corner Program

TYL - Salary Hike - Python Problem

5 Questions for TYL on Strings(check if two string are anagrams)