В new метакласса проверяйте namespace нового класса: если он объявляет do_not_override, а метод уже есть у базового класса, выбрасывайте TypeError до создания класса.
2. Напиши метакласс, который запрещает классам-наследникам переопределять метод do_not_override, если он есть в базовом классе.
В __new__ метакласса проверяйте namespace нового класса: если он объявляет do_not_override, а метод уже есть у базового класса, выбрасывайте TypeError до создания класса.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
2. Напиши метакласс, который запрещает классам-наследникам переопределять метод do_not_override, если он есть в базовом классе.
Ответ
В new метакласса проверяйте namespace нового класса: если он объявляет do_not_override, а метод уже есть у базового класса, выбрасывайте TypeError до создания класса.
Минимальный вариант проверяет переопределение при объявлении наследника:
class NoOverride(type):
def __new__(mcls, name, bases, namespace, **kwargs):
inherited = any(hasattr(base, 'do_not_override')
for base in bases)
if inherited and 'do_not_override' in namespace:
raise TypeError('do_not_override is final')
return super().__new__(mcls, name, bases, namespace, **kwargs)
class Base(metaclass=NoOverride):
def do_not_override(self):
return 'fixed'
Проверка учитывает метод, унаследованный базой от более дальнего предка. Она не защищает от последующего monkey patching или затенения через сложное множественное наследование; для такого расширенного контракта нужны дополнительные проверки. Это ограничение API, не граница безопасности.