A post was merged into an existing topic: How can I access Pieter’s grade after it has been added?
7 posts were split to a new topic: What do we actually need to do in the last additional “challenge”
28 posts were split to a new topic: How do i print the results of self.grades using the repr method?
changing grade to grade.score worked for me.
print(grade) gives you <main.Grade object at 0x7feebe938b38> or something like that
print(grade.score) gives you a int
the int you can append to self.grades
You’ll want to append Grade objects (instances of the Grade class) not just the score. If all we want to append is the score, there’d be no point in creating Grade objects.
5 posts were split to a new topic: What’s going wrong despite using “grade.score” to append “self.grades”
This is my first post here, so here goes…
I also fought with the solution to the average score section of this Review. I read all the posts here and came up with this solution. I’m still not feeling like I fully understand this lesson, but I am learning a lot, and I am happy to get this working!
Under “class Student:”
def get_average(self):
#var. to hold scores as added
temp = 0
#var. to get length of how many scores are in grades
avgl = len(self.grades)
#var. to limit number of loops for while loop
counter = 0
while counter < avgl:
#adds each score to the total. The counter var will advance and allow access to each list item.
temp += self.grades[counter].score
#advances count for loop
counter += 1
#calculate average of scores
avg = temp / avgl
return avg
pieter.add_grade(Grade(100))
pieter.add_grade(Grade(80))
print(pieter.get_average())
90.0
If I missed the point of the exercise, any input is welcome please!
Given the amount of iterations is know, I would use a for loop.
As would I. Was just going to comment when I saw this.
We can further abstract away self
by iterating over, self.grades
.
for grade in self.grades: # grade is a Grade object
t += grade.score
sample code:
Output for the print statements is shown below :
print(roger)
print(sandro)
print(pieter)
print("=====================")
print(f"Was {roger.name} in attendance on '24 Jan 2020?' : {roger.get_attendance('01/22/2020')}")
Hi, I am struggleling with an error who tells me it missing a postionnal argument “self”, on the condition “if Grade.is _passing():”
After some research, it looks like it is because I should create an instance of my class before to call a method. But my objects already exist (pieter = Student(“Pieter Bruegel the Elder”, 8) and pieter_grade = Grade([85, 77, 100]) ).
Someone to show me the way please?
class Student:
def __init__(self, name, year):
self.name = name
self.year = year
self.grades = []
def __repr__(self):
if Grade.is_passing():
return "Student: " + str(self.name) +", " + str(self.year) + " years, grades is " + str(self.grades[0]) + ", student is passing"
else:
return "Student: " + str(self.name) +", " + str(self.year) + " years, grades is " + str(self.grades[0]) + ", student is not passing"
def add_grade(self, grade):
if isinstance(grade, Grade):
self.grades.append(grade)
####################################################
roger = Student("Roger van der Weyden", 10)
sandro = Student("Sandro Botticelli", 12)
pieter = Student("Pieter Bruegel the Elder", 8)
###################################################
class Grade:
minimum_passing = 65
def __init__(self, score):
self.score = score
self.total = 0
for num in score:
self.total += num
def __repr__(self):
average = self.total / len(self.score)
self.result = str(round(average, 2))
return "Average score is: " + str(self.result)
def is_passing(self):
if float(self.result) >= float(self.minimum_passing):
#return print("passing") #return None in addition on the print, why?
return True
else:
#return print("not passing") #return None in addition on the print, why?
return False
####################################################
pieter_grade = Grade([85, 77, 100])
pieter.add_grade(pieter_grade)
print(pieter)
####################################################
We can see where that is going to be a problem.
grades
is a list of Grade objects, each with a score attribute and the is_passing method of their parent class. An individual grade could be assessed but one doubts there is only a single grade throughout the term so an average of the scores would be a more likely desired outcome. We can test the average to see its is_passing
status.
One could write a get_average()
method in the Student class.
def get_average(self):
return sum([x.score for x in self.grades]) / len(self.grades)
Now we can compute any average at any point in the term to monitor progress.
f"{Grade(get_average()).score.is_passing()}" # transient instance
The Grade.is_passing()
method can be simplified:
return self.score >= self.minimum_passing
In my view, the Grade object should be simple. A score, and an is_passing method. None of the other logic you have above. Let the Student instance have access to all utility methods except is_passing.
Thank you @mtf for your support, I finally reorganised the structure.
I noticed if you removed the “.score” in [x.score for x in self.grades]
, it will print the memory adress of the Grade object, so I understand this is like the “self” of a method, it refers to the object created.
Also, maybe I didn’t catch what you try to told me, but
def get_average(self):
return sum([x.score for x in self.grades]) / len(self.grades)
didn’t work, it try to add list together, I fixed it with:
def get_average(self):
self.average = round(sum([y for x in self.grades for y in x.score]) / len([y for x in self.grades for y in x.score]),2)
thanks for that you forced me to work on list comprehension!
I finally put my is_passing() method in the student class, because I could not figure out to access to it when it was in the Grade class.
My final code is that:
class Student:
def __init__(self, name, year):
self.name = name
self.year = year
self.grades = []
self.average = 0
self.passing = ""
def __repr__(self):
return str(self.name) + ", " + str(self.year) + " years" + ", average is: " + str(self.average) + ", " + self.passing
def add_grade(self, grade):
if isinstance(grade, Grade):
self.grades.append(grade)
return self.grades
def get_average(self):
self.average = round(sum([y for x in self.grades for y in x.score]) / len([y for x in self.grades for y in x.score]),2)
def is_passing(self):
if self.average >= Grade.minimum_passing:
self.passing = "passing"
else:
self.passing = "not passing"
class Grade:
minimum_passing = 65
def __init__(self, score):
self.score = score
####################################################
pieter = Student("Pieter Bruegel the Elder", 8)
pieter_grade = Grade([10, 5, 2])
pieter.add_grade(pieter_grade)
pieter.get_average()
pieter.is_passing()
print(pieter)
####################################################
Given that all the values in the grades
array are Grade
objects, each with a score attribute, when we iterate over the objects individually then our iteration variable fills in for self.
Each x
is a self
as in owner object, hence, x.score
.
There are two objects, the instance, which is represented by self
and the Grade object, which we give a name within the comprehension.
[x.score for x in self.grades]
should result in a list of grade scores (numbers) which we can add up using the sum()
function. Not sure why it wouldn’t work for you.
Our classes look quite a bit different. Recall that we mentioned leaving the is_passing method in the Grade class. We shouldn’t need the two attributes, average
or passing
since those values are dynamically determined on any one instance of the Student class.
At any length, if you have it running, then that’s a plus. When it comes time to review or get in more practice, loop back around to this and give it another go to see if it can be simplified.