Cant find a variable in a list

Question:

I wrote this code as a part of a course I am taking right now, and even though I asked some friends to debug it we didn’t manage to find the problem in the code. It throws an error that the variable I am looking for cannot be found in the list, even though I can find it when I debug and the functions I use are supposed to find it. Can anyone help me fix it?

class Grade:
    def __init__(self, grade_val, grade_weight):
        if grade_weight > 4 or grade_weight < 1 or grade_val > 100 or grade_val < 0:
            print("Grade weight should be a number between 1 and 4 and Grade value should be between 0 and 100")
        else:
            self.grade_value = grade_val
            self.grade_weight = grade_weight

    def get_val(self):
        return self.grade_value

    def get_weight(self):
        return self.grade_weight


class Subject:
    def __init__(self, subject_name):
        self.name = subject_name
        self.grades = []

    def add_grade(self, grade):
        if not isinstance(grade, Grade):
            return "Wrong input"
        self.grades.append(grade)

    def avg(self):
        counter = 0
        grade_sum = 0
        for grade in self.grades:
            grade_sum += grade.get_val() * grade.get_weight()
            counter += grade.get_weight()
        return grade_sum / counter

    def __str__(self):
        grades_str = ""
        for grade in self.grades:
            grades_str += f"Val: {grade.get_val()} Weight: {grade.get_weight()}.   "
        return grades_str

    def __len__(self):
        return len(self.grades)

    def __lt__(self, other):
        if not isinstance(other, Subject):
            return "Wrong input"
        if self.avg() > other.avg():
            return "Self avg is bigger"
        if self.avg() < other.avg():
            return "Other avg is bigger"
        return "Avgs are equal"

    def __gt__(self, other):
        self.__lt__(other)


class Student:
    def __init__(self, name, s_id):
        self.name = name
        self.id = s_id
        self.subjects = []

    def add_sub(self, subject):
        if not isinstance(subject, Subject):
            return "Wrong input"
        self.subjects.append(subject)

    def add_grade(self, subject, grade):
        if not isinstance(grade, Grade):
            return "Wrong input"
        for subj in self.subjects:
            if subj.name == subject:
                subj.add_grade(grade)
        # self.subjects[self.subjects.index(subject)].add_grade(grade)

    def get_subs(self):
        return self.subjects

    def sub_avg(self, subject):
        return self.subjects[self.subjects.index(subject)].avg()

    def student_avg(self):
        summ = 0
        for subject in self.subjects:
            summ += subject.avg()
        return summ / self.subjects.len()


std = Student("Ofek", 42069)
std.add_sub(Subject("Math"))
# subs = std.get_subs()
# for sub in subs:
#     print(sub.name)
#     print(std.subjects[0].name)
std.add_grade("Math", Grade(98, 4))
std.add_grade("Math", Grade(92, 2))
std.add_sub(Subject("English"))
std.add_grade("English", Grade(85, 3))
print(std.sub_avg("Math"))
print(std.student_avg())


Traceback (most recent call last):
  File "C:Usersbar_mDesktopDevOpsPythonCodegrade_exe.py", line 99, in <module>
    print(std.sub_avg("Math"))
          ^^^^^^^^^^^^^^^^^^^
  File "C:Usersbar_mDesktopDevOpsPythonCodegrade_exe.py", line 80, in sub_avg
    return self.subjects[self.subjects.index(subject)].avg()
                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ValueError: 'Math' is not in list

Thx for the support in advance <3

Asked By: happymancer

||

Answers:

In sub_avg(), subject is a string that names a subject, but self.subjects is a list of Subject instances, not strings. You need to loop through the list looking for the one with that name.

def sub_avg(self, subject):
    for sub in self.subjects:
        if sub.name == subject:
            return sub.avg()
    raise KeyError(f"Subject {subject} not found in {self}")
Answered By: Barmar
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.