Python Classes Review - Further Practice Discussion

Did anyone try the the bonus practice in the review?

I seem to be having a challenge with the including the get_average() method.

One thing I observed was that the .grades was printing out in string representation form and when I included repr in an attempt to debug it, I got a ‘NoneType’ error traceback. Here is code below: (can anyone spot the error?)

class Student(object):
attendance = {}
def init(self, name, year):
self.name = name
self.year = year
self.grades = list()

def repr(self):
print(self.name, self.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
def is_passing(self):
if self.score > self.minimum_passing:
return “Yes”
else:
return “No”

value = Grade(100)
pieter.add_grade(value)

print(pieter.grades)

One thing that you did wrong is writing init keyword without underscores before and after it. So it should be like this to work: __init__.

2 Likes

I have the same question, did anybody figure it out

I just figured you need to add the repr() method in your grade class to print out the list of grades without just showing the memory location

class Grade:
minimum_passing = 65

def init(self, score):
self.score = score
def repr(self):
return str(self.score)

3 Likes

Hey thanks.

I did a copy and paste but that didnt work…I have it in dunder in the actual code

Hey thanks. That worked.

But I’m still stuck on why my get_average does not work.

Did you by chance use a for loop?

def get_average(self):
total = 0
for grade in self.grades:
total += grade
return total

I get unsupported type error.

In case you struggled with this as well. I just made Grade a subclass of ‘int’ and it seemed to recognize this.

2 Likes

My code is follow:
class Student:
def init(self, name, year):
self.name = name
self.year = year
self.grades =
self.attendance = {}

def add_grade(self, grade):
if type(grade) == Grade:
self.grades.append(grade.score)
def get_average(self):
return sum(self.grades)/ len(self.grades)

1 Like
self.grades = []

When I use the add_grade method as defined below

def add_grade(self, grade):
  if type(grade) is Grade:
    self.grades.append(grade)
pieter.add_grade(Grade(100))

and then print out Pieter’s grades list

print(pieter.grades)

I see that Grade(100) has been appended to the list, rather than 100, the integer. I get a result of [<__main__.Grade object at 0x7f6ace7406a0>] when printed out.

How might the add_grade method yield integers into Pieter’s grades list?

If I enter pieter.add_grade(100), it doesn’t satisfy the method because the integer 100 is not of class Grade.

Would I have to add a grade argument into the constructor and then simply append self.grade into the self.grades list? I’m just not sure what solution the exercise wants me to find… A list with content such as [<__main__.Grade object at 0x7f6ace7406a0>] does not strike me as useful.

This is in reference to parts 7 + 8 of the exercise.

One suspects that grade has an attribute we’re not polling.

If it is an instance, then just the name won’t mean much.

Ah yes, I see it should be grade.score. I think there is some confusion over this because the solution given for the exercise defines the method as:

  def add_grade(self, grade):
    if type(grade) is Grade:
      self.grades.append(grade)

when what we really want is:

  def add_grade(self, grade):
    if type(grade) is Grade:
      self.grades.append(grade.score)
10 Likes

self.grades.append(grade)
–> self.grades.append(grade.score)

3 Likes

The last step in this exercise gives some additional things you could do with the classes’ you just created, and one of those things is:
“Write a Student method get_average() that returns the student’s average score.”

First here is the code I am working with, I have changed it slightly from what you end up with in the exercise for the sake of solving the “get_average” problem.

class Student:
    def __init__(self):
        self.grades = []

    def add_grade(self, grade):
        if type(grade) is Grade:
            self.grades.append(grade)

    def get_average(self):
        return  #???

class Grade:
    def __init__(self, score):
        self.score = score


S = Student()

grade_obj_1 = Grade(100)
grade_obj_2 = Grade(50)

S.add_grade(grade_obj_1)
S.add_grade(grade_obj_2)

At this point I have no idea how I could go about getting the average of a students grades, because they have been added to the grades list as Grade objects, so I cannot preform any kind of calculation on to return a value.

the average is the sum divided by the length, and within the get_average method you have access to the self.grades instance variable.

1 Like

But the self.grades variable is just a list with 2 Grade objects in it.

print(S.grades)

Output: 
[<__main__.Grade object at 0x7f150a301668>, <__main__.Grade object at 0x7f150a3016a0>]

And if I try to do any kind of calculation on these Grade objects I get an error

S.grades[0] + S.grades[1]

Output:
  File "script.py", line 25, in <module>
    S.grades[0] + S.grades[1]
TypeError: unsupported operand type(s) for +: 'Grade' and 'Grade'

I get the same error if I try to do the calculation in the get_average method in the Student Class.
Could you maybe provide an example of how I could preform calculations on these objects?

Hello, @fox3773.

grades is a list containing Grade objects as you’ve mentioned. You need to access the property of the Grade object that contains the value. You are almost there with S.grades[0]. That is the first grade object. How do you access its property?

Hint
class Grade:
    def __init__(self, score):
        self.score = score
             ^^^^^
1 Like

Thanks @midlindner,
This really did help, but it still took me a long time to figure out I was looking for S.grades[0].score
I am definitely going to need some more time to get a handle on classes.

Since we are instantiating a Grade class within the argument of the add_grade() method, it doesn’t get assigned as a referable instance except by accessing the grades instance variable (the list of grades).

pieter.add_grade(Grade(100))
  def get_grades(self):
    return [x.score for x in self.grades]
grades = pieter.get_grades()
print (grades[0])    # 100
1 Like