FAQ: Learn Python: Classes - Review

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?

class Student: def __init__(self, name, year): self.name = name self.year = year self.grades = [] def add_grade(self, grade): if type(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 pieter.add_grade(Grade(100))
1 Like

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.

1 Like

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.

1 Like