MRO в Python: проверка порядка примесей в наследовании

Напишите решение на Python и проверьте его на странице.

Другие упражнения по этой теме: Метаклассы и init_subclass Python: задачи на проверку классов.

Порядок примеси финализации

В модуле управления ресурсами предусмотрен вспомогательный класс-примесь CleanupMixin. Метод финализации этой примеси обязан выполняться строго после бизнес-логики целевых сервисов, чтобы освобождение ресурсов не опережало их использование. При сложном множественном наследовании разработчики могут случайно указать классы в некорректном порядке, нарушив задуманную последовательность вызовов.

Чтобы защитить архитектуру от подобных сбоев ещё на этапе конструирования типов, базовый сервисный класс анализирует порядок разрешения методов cls.__mro__ внутри специального метода __init_subclass__. Если среди предков нового класса обнаруживается CleanupMixin, но в кортеже MRO эта примесь оказывается строго раньше (левее) самого базового сервисного класса, хук немедленно пресекает создание такого потомка исключением TypeError.

Реализуйте базовый сервисный класс, который проверяет вычисленный порядок предков при создании наследников и отклоняет ошибочное объявление классов.

Что уже дано

В среде исполнения уже объявлен маркерный класс-примесь CleanupMixin. Реализовывать методы очистки или алгоритм работы самой примеси не требуется.

В заготовке объявлен класс ServiceBase, в котором вам предстоит написать тело метода __init_subclass__.

Что нужно сделать

Реализуйте класс ServiceBase со специальным методом __init_subclass__(cls, **kwargs):

  • Внутри __init_subclass__ проверяйте порядок разрешения методов только что созданного класса через cls.__mro__.
  • Если точный класс CleanupMixin присутствует в cls.__mro__ и располагается в этом кортеже строго раньше (имеет меньший индекс), чем ServiceBase, создание класса должно быть отклонено исключением семейства TypeError.
  • Если CleanupMixin отсутствует в MRO либо располагается строго после ServiceBase, объявление класса должно завершаться успешно.
  • Правило действует как при прямом, так и при косвенном наследовании. Посторонние классы с такими же именами считаются независимыми сущностями: проверять нужно строгое совпадение идентичности классов CleanupMixin и ServiceBase.
  • Не изменяйте и не переупорядочивайте исходный кортеж родителей bases, не откладывайте проверку до инстанцирования объектов и не ограничивайте проверку только прямыми предками.
  • Передавайте необработанные именованные параметры в вызов super().__init_subclass__(**kwargs).

Иерархии в тестах конечны, согласованы по алгоритму C3, содержат не более 100 предков и до 1000 объявлений классов за один тестовый прогон. Кастомные метаклассы и метод __mro_entries__ во входных данных не используются.

Ввод и вывод

Стандартные потоки ввода stdin и вывода stdout в решении не используются: считывать ввод и вызывать print() не нужно. После выполнения кода учащегося проверяющая система считывает из пространства имён модуля класс верхнего уровня ServiceBase и тестирует создание классов-наследников.

Пример использования

class GoodService(ServiceBase, CleanupMixin):
    pass

print(issubclass(GoodService, ServiceBase))
try:
    class BadService(CleanupMixin, ServiceBase):
        pass
except TypeError:
    print('rejected at class creation')

Вывод:

True
rejected at class creation
РешениеPython

Без регистрации. Гостевая проверка не сохраняет прогресс. Для сохранения перейдите к уроку.

Отправьте решение, чтобы увидеть результаты тестов.

Связанные задачи