How to check for passing in the Grade class?

After writing the is_passing method, how do we use it on one of the students we made to see if they’re passing?

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)
class Grade:
  minimum_passing = 65
  def __init__(self, score):
    self.score = score

  def is_passing(self):
    if self.score >= Grade.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(Grade(100))
x = Grade(70)
print(x.is_passing())
print(pieter.grades.is_passing())

print(x.is_passing()) works fine.
The line after it doesn’t work, and I’m not sure how to write to check if Pieter is passing. He has a Grade of 100, so shouldn’t there be a way to check that?

Did you try,

pieter.is_passing()

?

I did! It gave me,
AttributeError: 'Student' object has no attribute 'is_passing'

It looks as though there might be a missing method to obtain the average score. That result would be what to call the is_passing method on…

print ( Grade(pieter.get_average()).is_passing() )

It’s a thought.

1 Like

Thanks, I’ll give that a try! I didn’t write the average method yet, but I’ll do that and see if it completes the puzzle.

1 Like

Man, I breezed through all of Python up until this point, and this is just an insane roadblock that I’m not getting through at all ;(

Anyway, I’m having trouble using the is_passing() method. Here is my code:

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)
class Grade:
  minimum_passing = 65
  def __init__(self, score):
    self.score = score

  def is_passing(self):
    if self.score >= Grade.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(Grade(100))
x = Grade(70)
print(x.is_passing())
pieter.grade.is_passing()

When I do that, like you suggested, I get an attribute error:
AttributeError: 'Student' object has no attribute 'grade'

Any ideas? x.is_passing works fine.

1 Like

here:

pieter.grade.is_passing()

does pieter (which is instance of Student class) have a grade attribute? lets see:

    self.name = name
    self.year = year
    self.grades = []

i only see name, year and grades attribute

here:

def add_grade(self, grade):

grade is a parameter of the add_grade method, just like functions, scope rules apply.

in the add_grade method we add the grade to the array (which is an attribute of Student, maybe we could use this?

1 Like

EDIT:
Ah!! I got it!!
I tried to switch it to
pieter.grades.is_passing()

and it said that wouldn’t work on a list, so I wrote a for loop like

for grade in pieter.grades:
  print(grade.is_passing())

And that worked!! Thanks for calling attention to that!

1 Like

Would checking each grade in turn be any indication of having a passing grade? Not really.

There is a method missing in the Student class…

Write a Student method get_average() that returns the student’s average score.

It is in this way that we can obtain a single grade to test.

average = pieter.get_average()

There is no way to tie this to Grade as an instance so we create a transient instance using that average and then call the is_passing() method on that instance.

print ( Grade(average).is_passing() )
2 Likes

Hi,

I am trying to print out the contents of self.grades with repr but it does not work.
What am I missing here?
Thanks!

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)
      return self.grades
    else:
      pass

     
  def get_average(self):
    for student in self.grades:
      return student
  
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
    
  def is_passing(self):
    if self.score > Grade.minimum_passing:
      return True
    else:
      return False
     
    def __repr__(self):
      print('Your grade is {grade}'.format(grade = self.grades))

pieter_grade = Grade(60)
pieter.add_grade(pieter_grade)
print(pieter.grades)

i don’t see you attempting to print pieter_grade anywhere?

Also, the __repr__ method seems to be nested within the is_passing function

furthermore, the __repr__ method seems to be part of Grade class, while you seem to intent to change the default representation of the Student class.

Grade has no attribute grades.

After I added a grade to add_grade, I actually want to fetch the content of self.grades list. I tried it with simply print(pieter.grades) but it just print the object id

pieter_grade = Grade(60)
pieter.add_grade(pieter_grade)
print(pieter.grades)

When I try to to embed repr in Students to make pieter.grades visible, it does not give me anything.

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)
      return self.grades
    else:
      pass

  def __repr__(self):
    return 'Your grade is {grade}'.format(grade = self.grades)
  
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
    
  def is_passing(self):
    if self.score > Grade.minimum_passing:
      return True
    else:
      return False

pieter_grade = Grade(60)
pieter.add_grade(pieter_grade)
print(pieter_grade.is_passing())
print(pieter.grades)

I guess, I still haven’t understood how __repr__works.
Thanks

You’re getting closer, though. Now you have it in the correct class.

__repr__() will return a representation of the object instance.

  def __repr__(self):
    return f"Name: {self.name}\nYear: {self.year}\nGrade: {self.get_average()}"

The above assumes your Student class has a get_average method. We access this by printing the instance…

 print (pieter)

Output

Name: Pieter Bruegel the Elder
Year: 8
Grade: 92.75
1 Like

Ok, I came up with this solution, but I think it is not very pythonic.

Can you please review and give me some recommendations for cleaner code. Is there a way to write the add_grade() and is_passing() calls at the end in one line?

Thanks!

class Student:
  
  def __init__(self, name, year, day):
    self.name = name
    self.year = year
    self.day = day
    
    self.grades = []
    
    self.attendance ={'Monday':True, 
                    'Tuesday':False, 
                    'Wednesday':False,
                   'Thursday':True,
                   'Friday':True}
  
  def add_grade(self, grade):
    if type(grade) == Grade:
      self.grades.append(grade)
    
  def get_average(self):
    x = 0
    for student in self.grades:
      x += student.score
      return x/(len(self.grades))
  
  def availability(self):
    for key, val in self.attendance.items():
      if key == self.day:
        return val
    
       
  def __repr__(self):
    return f'Name: {self.name}\nYear: {self.year}\nGrade:{self.get_average()}\Attendance: {self.availability()}'
  
  
pieter = Student('Pieter Bruegel the Elder', 8, 'Wednesday')


class Grade:
  minimum_passing = 65
  
  def __init__(self, score):
    self.score = score
    
  def is_passing(self):
    if self.score > Grade.minimum_passing:
      return True
    else:
      return False

pieter_grade = Grade(100)
pieter_grade1 = Grade(80)
pieter_grade2 = Grade(60)

pieter.add_grade(pieter_grade)
pieter.add_grade(pieter_grade1)
pieter.add_grade(pieter_grade2)

pieter_grade.is_passing()
pieter_grade1.is_passing()
pieter_grade2.is_passing()

pieter.get_average()
pieter.availability()

print(pieter)
def is_passing(self): 
  if self.score > Grade.minimum_passing: 
    return True 
  else: 
    return False

Consider the expression,

self.score >= Grade.minimum_passing

It has only two possible outcomes, either it is a true assertion, or it is false. That means we can return it without the if..else coming into play, at all.

As for the add_grade method, making it into a one-line return will take some convoluted logic that will not be superior to the simple if question, even if it does look clever.

self.grades += [grade] if type(grade) == Grade else []
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)

   else:

     return

class Grade:

  minimum_passing = 65

  def __init__(self, score):

     self.score = score

  def is_passing(self):

     if self.score > self.minimum_passing:

      return True

     return False

roger = Student("Roger van der Weyden", 10)

sandro = Student("Sandro Botticelli", 12)

pieter = Student("Pieter Bruegel the Elder", 8)

pieter.add_grade(Grade(100))

How can I check is_passing method here without having get_average method?

Thank you in advance

is_passing currently can only handle individual grades/scores.

Thank you @stetim94. Please can you let me know , how can I modify it to obtain output as per assignment ?

You have completed the exercise? Now you simple call is_passing on each grade to see if they passed the exam.