✅ Решения заданий

⚠️ Рекомендация: попробуйте решить задания самостоятельно, прежде чем смотреть ответы. Решения — это последняя инстанция, когда собственные попытки исчерпаны.

⚡ Кратко

  • Задание 1: MRO D → B → C → A → object, вывод Hello from C.
  • Задание 2: ответ b.
  • Задание 3: ответ a — Saving….
  • Задание 4: 1-b, 2-c, 3-a.
  • Задание 5: агрегация.
  • Задание 6: класс Student с __str__ и notify.
  • Задание 7: класс Course со списком студентов.

Решение 1. Порядок поиска метода

Порядок MRO: D → B → C → A → object.

Python ищет метод greet сначала в D, затем в B. B не переопределяет метод, поэтому поиск идёт в C. Метод найден в C, и Hello from C печатается. До A Python не доходит.

print(D.__mro__)
# (<class '__main__.D'>, <class '__main__.B'>,
#  <class '__main__.C'>, <class '__main__.A'>,
#  <class 'object'>)

Решение 2. Назначение super()

Правильный ответ: b.

  • a — неверно: super() не привязан к конкретному родителю.
  • b — верно: super() переходит к следующему методу в MRO.
  • c — неверно: чтобы заменить метод, достаточно переопределить его без super().
  • d — неверно: super() не обращается напрямую к object.

Решение 3. Конфликт имён в миксинах

Правильный ответ: a — Saving….

Класс Document(SaveMixin, PrintMixin) наследует SaveMixin первым. При совпадающих именах методов Python выбирает метод первого подходящего родителя слева направо. Поэтому вызывается SaveMixin.process.

Решение 4. Сопоставьте понятия

Правильный ответ: 1-b, 2-c, 3-a.

  • Композиция — объект создаётся и управляется внешним объектом (b).
  • Агрегация — объект передаётся извне и может существовать отдельно (c).
  • Вложенный класс — класс определён внутри другого класса (a).

Решение 5. Тип связи

Правильный ответ: b — агрегация.

Объект teacher передаётся извне и может существовать отдельно от Course. Course не управляет созданием преподавателя.

Решение 6. Класс Student

Класс содержит имя и email, строковое представление и метод для отправки уведомлений.

class Student:
    def __init__(self, name: str, email: str) -> None:
        self.name = name
        self.email = email

    def __str__(self) -> str:
        return self.name

    def notify(self, message: str) -> None:
        print(f"Email to {self.email}: {message}")


student = Student("Alice", "alice@example.com")
print(student)
student.notify("You have been enrolled.")

Решение 7. Класс Course

Класс Course агрегирует объекты Student и делегирует им отправку уведомлений.

# Класс Student из решения 6 включён сюда, чтобы блок можно было запустить отдельно.
class Student:
    def __init__(self, name: str, email: str) -> None:
        self.name = name
        self.email = email

    def __str__(self) -> str:
        return self.name

    def notify(self, message: str) -> None:
        print(f"Email to {self.email}: {message}")


class Course:
    def __init__(self, title: str) -> None:
        self.title = title
        self.students: list[Student] = []

    def add_student(self, student: Student) -> None:
        self.students.append(student)

    def show_students(self) -> None:
        print(f"Students enrolled in {self.title}:")
        for student in self.students:
            print(f"- {student}")

    def notify_all(self, message: str) -> None:
        for student in self.students:
            student.notify(message)


s1 = Student("Alice", "alice@example.com")
s2 = Student("Bob", "bob@example.com")

course = Course("Python OOP")
course.add_student(s1)
course.add_student(s2)

course.show_students()
course.notify_all("Welcome to the course!")

Логика: Course не наследует Student, а содержит список студентов. Это агрегация: студенты существуют независимо от курса.

Проверить по документации: про super(), MRO и множественное наследование см. Multiple Inheritance; про типы коллекций — typing.