Как добраться до переменной в магическом методе
Есть такой вот студент
class Student:
def __init__(self, name, surname, gender):
self.name = name
self.surname = surname
self.gender = gender
self.finished_courses = []
self.courses_in_progress = []
self.grades = {}
def __str__(self):
average_grade = sum(elem for num in self.grades.values() for elem in num) / len(
[elem for num in self.grades.values() for elem in num])
return f'''Имя: {self.name}
Фамилия: {self.surname}
Средняя оценка за домашние задания: {average_grade}
Курсы в процессе изучения: {self.courses_in_progress}
Завершенные курсы: {self.finished_courses}'''
Мне нужна его переменная average_grade чтобы сравнивать студентов по средней оценке. Но если ставить ее в __init__ начинает ругаться на division by zero. Может есть способ достать ее из __str__?
Ответы (2 шт):
Можно добавить метод для вычисления средней оценки:
class Student:
def __init__(self, name, surname, gender):
self.name = name
self.surname = surname
self.gender = gender
self.finished_courses = []
self.courses_in_progress = []
self.grades = {}
def get_average_grade(self):
return sum(elem for num in self.grades.values() for elem in num) / len(
[elem for num in self.grades.values() for elem in num])
def __str__(self):
return f'''Имя: {self.name}
Фамилия: {self.surname}
Средняя оценка за домашние задания: {self.get_average_grade()}
Курсы в процессе изучения: {self.courses_in_progress}
Завершенные курсы: {self.finished_courses}'''
Потом вызываете его где вам нужно.
Либо делаете вычисляемое поле - тот же самый метод, но с декоратором @property. Обращение к нему как будто это обычное поле:
class Student:
def __init__(self, name, surname, gender):
self.name = name
self.surname = surname
self.gender = gender
self.finished_courses = []
self.courses_in_progress = []
self.grades = {}
@property
def average_grade(self):
return sum(elem for num in self.grades.values() for elem in num) / len(
[elem for num in self.grades.values() for elem in num])
def __str__(self):
return f'''Имя: {self.name}
Фамилия: {self.surname}
Средняя оценка за домашние задания: {self.average_grade}
Курсы в процессе изучения: {self.courses_in_progress}
Завершенные курсы: {self.finished_courses}'''
Выражение elem for num in self.grades.values() for elem in num лучше вынести в отдельную переменную, вычислить один раз, потом делить его сумму на его длину:
@property
def average_grade(self):
grades = [elem for num in self.grades.values() for elem in num]
return sum(grades) / len(grades)
Как вариант сделать инициализировать привптную переменную, которой будет присваиваться значение и через специальный метод она будет возвращаться
Пример:
class Student:
def __init__(self, name, surname, gender):
self.name = name
self.surname = surname
self.gender = gender
self.finished_courses = []
self.courses_in_progress = []
self.grades = {}
self.__average_grade = None
def aver(self):
return self.__average_grade
def __str__(self):
average_grade = sum(elem for num in self.grades.values() for elem in num) / len(
[elem for num in self.grades.values() for elem in num])
self._average_grade = average_grade
return f'''Имя: {self.name}
Фамилия: {self.surname}
Средняя оценка за домашние задания: {average_grade}
Курсы в процессе изучения: {self.courses_in_progress}
Завершенные курсы: {self.finished_courses}'''
st = Student('Евгений', 'Малевичев', 'Male')
print(st.aver())