I don’t understand, if Python reads code line by line, top to bottom, then how can we check that the type of grade is that of the Grade class before we’ve defined the Grade class?
This might need a little more information as you don’t seem to be checking anything at any point in this code but the short answer is that you don’t. Typically you’d have function and class definitions at the top of your script (or more likely still in another module that you import) so they’d be defined before you attempt to use them.
See lines 7 - “if type(grade) == Grade” - and 14, where the Grade class is defined.
You can use names that yet to be defined in the body of the function since they only really need to be found at the time when you call it. Since you never actually call this function in the given example then it never actually has to look for Grade
.
A rather blunt example-
def func():
print(x)
x = 3
func()
If you tried to call it before Grade
was defined in an accessible scope then it would throw a Name Error.
Here is my solution.
class Student:
def __init__(self, name, year):
self.name = name
self.year = year
self.grades = []
self.attendance = {}
def get_average(self):
grade_sum = 0
count = 0
for i in self.grades:
count += 1
grade_sum += i
return grade_sum / count
def add_grade(self, grade):
if type(grade) is int:
self.grades.append(grade)
class Grade:
minimum_passing = 65
def __init__(self, score):
self.score = score
def is_passing(self, score):
if score >= self.minimum_passing:
return True
else:
return False
roger = Student('Roger van der Weyden', 10)
sandro = Student('Sandro Botticelli', 12)
pieter = Student('Pieter Bruegel the Elder', 8)
pieter.add_grade(100)
pieter.add_grade(80)
pieter.add_grade(70)
pieter.add_grade(89)
student_score = Grade(0)
print(student_score.is_passing(89))
print(pieter.grades)
print(pieter.get_average())
pieter.attendance['01/01/22'] = 'Present'
pieter.attendance['01/02/22'] = 'Absent'
pieter.attendance['01/03/22'] = 'Present'
print(pieter.attendance)
I did have trouble with this piece:
def add_grade(self, grade):
if type(grade) is int:
self.grades.append(grade)
the assignment ask:
" Add an .add_grade()
method to Student
that takes a parameter, grade
.
.add_grade()
should verify that grade
is of type Grade
and if so, add it to the Student
‘s .grades
.
If grade
isn’t an instance of Grade
then .add_grade()
should do nothing."
this made my original code:
def add_grade(self, grade):
if type(grade) is Grade:
self.grades.append(grade)
but then it caused problems with adding grades and finding averages so I changed it to what it is in my code solution. Curious if there was something I was missing. I think my code gets the right answers but not exactly the way the assignment wanted me to. I figure if the grade is just an int my code is fine, but I dont think it would have passed had I started with it going through the check points. I changed my code when I was doing the extra questions at the end.
Remember that Grade has a 'score'
attribute that we need to poll when computing the average.
Hello,
In question 7, why do we need to include Grade
in pieter.add_grade(Grade(100))
? Why can’t we just write pieter.add_grade(100)
?
Thank you!
100 is not a Grade object. In order for our classes to work together we need to keep them as objects that can have their own methods.
https://www.codecademy.com/workspaces/61f406114ad323964b6793a8
In the project challenge: “Create a game using classes and objects”,
i’m calling .approach.child
method, the methods switches .want_to_play
parameter to True
. I don’t know how to pass the Child
instance as child_1
into a specific Activity
. ideally i want .approach_child
or any other method of my own to pass it. If not possible, at least __repr__
to be able to pass it.
Not only pass the parameter, but also to actually call a specific instance of Activity
.
Like most people here I definitely had a hard time with this exercise and especially the bonus practice questions at the end.
So after finally figuring out how to get_average
I played around a little bit with functions which we learned in another lesson. My thinking was, it was time consuming to manually run individual “grade assignments” through classes and adding them to a student, get average, etc. So I defined some functions that could take in a list of grades and use the classes we created in the lessons.
Let me know what you think (feedback appreciated). Here is the link to the full code: https://www.codecademy.com/workspaces/62a839c8b0fe32e4008f1008
Some of the Forum posts definitely helped me understand classes a lot better and helped me remember details about classes that I quickly forgot after reading them.
Why doesn’t this line in the Student class throw a name error?
if type(grade) == Grade:
Grade hasn’t been defined yet so not sure what’s going on here
Edit: Actually it does throw an error when I tested it with some dummy code
s = Student(‘sam’, 43)
s.add_grade(5)
But the task still completed when I did the former. Weird
How do I use is_passing method in Grade using the numbers that are the grades defined in the instances of the Student class?
I can call it in Students class and use it to determine if the average student grade is passing or not. First I define it as a Grade instance then call the is_passing method from Grade. Is there a better way to use the is_passing method?
def get_average(self):
x = sum(self.get_grades())/len(self.grades)
y = Grade(x)
y_ = y.is_passing()
return “this is x: {x} and this is y: {y_}”.format(x=x, y_=y_)
class Grade:
minimum_passing = 65
def init(self,score):
self.score = score
def is_passing(self):
if self.score > self.minimum_passing:
return “PASS”
else:
return “FAIL”
I struggled with the following parts of this review exercise and was hoping to get some feedback.
Specifically:
- Computing the average grade and displaying it was hard. I had wanted to use the mean() function like this:
return mean(grade.score for grade in self.get_grades())
But that didn’t work. I now used a workaround that calculates the total and divides it by the # of grades. But it seems inefficient and verbose. How can I do this more simply?
-
What would be the most efficient way to insert multiple grades at once? Is that creating a list of grades within the get_grade() method and looping over them to append them to the self.grades list? How should the input parameters for the function look if you don’t want to pre-define the amount of grades you’ll be adding?
-
Do you have to add “self” as the first parameter in every function within a class (even ones other than init and repr)?
-
How do I print a list of grades? Printing
student.grades
Unfortunately returns a hash string, like:
Grades = [<__main__.Grade object at 0x7f1884912668>],
Is there any way to only extract the integer values?
You can find my total code below. Thank you!
from statistics import mean
# Create class
class Student:
# Initiate with constructor variables
def __init__(self, name, year):
self.name = name
self.year = year
self.grades = []
self.attendance = {}
def __repr__(self):
return self.name
def add_grade(self, grade): # Why do I have to specify self here, if this isn't a constructor?
if type(grade) is Grade:
self.grades.append(grade)
# Get average grade if student has reported grades.
def get_average(self):
if len(self.grades) > 0:
total = 0
for grade in self.grades:
total += grade.score
average = total / len(self.grades)
print(f'{self.name} average grade is', average)
return average
else:
print('No grades added yet.')
class Grade:
def __init__(self, score):
self.score = score
def is_passing(self, score):
minimum_passing = 65 # Had to move this to be inside the function.
if score >= minimum_passing:
return True
else:
return False
# Define instance variables for students.
roger = Student("Roger van der Weyden", 10)
sandro = Student("Sandro Botticelli", 12)
pieter = Student("Pieter Bruegel the Elder", 8)
# Add grades. Note I did not have to specify an argument for the 'self' parameter in either class method.
roger.add_grade(Grade(25))
sandro.add_grade(Grade(75))
pieter.add_grade(Grade(100))
# Add attendance
roger.attendance['27/04/2023'] = True
sandro.attendance['27/04/2023'] = True
pieter.attendance['27/04/2023'] = False
# Check if Pieter is passing.
print(Grade.is_passing(pieter, 100))
# Check avg grade
pieter.get_average()
# Print all information
students = [roger, sandro, pieter]
for student in students:
print(f"""
Name = {student.name},
Year = {student.year},
Avg grade = {student.get_average()},
Grades = {student.grades},
Attendance = {student.attendance}
""")
The Grade.is_passing() method applies to a particular grade, e.g. Grade(100). To print it, I believe you would need to iterate through each Grade.score and call the Grade.is_passing() function with the Grade.score as the input.
How can the if statement in the add_grade compare anything to the Grade class? isnt that something outside of the class it’s in and therefore something it cannot see?
It can see it because it has an instance of it accessible in grades
. The attribute we are looking for is, score
.