Что такое метаклассы в Python и для чего они используются
Что проверяют
Понимаете ли вы, что класс это объект, и знаете ли, где метакласс оправдан, а где это избыточная сложность.
Как отвечать
В Python класс это тоже объект, и создаёт его метакласс. По умолчанию type:
class User: pass
type(User) # <class 'type'>
User2 = type("User2", (), {"role": "admin"}) # то же самое динамическиМетакласс это класс, чьи экземпляры сами являются классами. Переопределяя __new__ или __init__ метакласса, вы вмешиваетесь в момент создания класса: можете проверить объявленные атрибуты, зарегистрировать класс в реестре, подставить методы, запретить наследование.
class Registry(type):
handlers = {}
def __new__(mcls, name, bases, ns):
cls = super().__new__(mcls, name, bases, ns)
if bases:
Registry.handlers[ns.get("event")] = cls
return clsГде это реально применяется: ORM (Django и SQLAlchemy превращают объявленные поля в описание таблицы), абстрактные базовые классы (ABCMeta), автоматическая регистрация плагинов, валидация интерфейса при объявлении.
Важная оговорка: почти всё это сегодня решается проще. __init_subclass__ покрывает регистрацию наследников, __set_name__ работает с дескрипторами, декоратор класса меняет уже созданный класс. Метакласс оправдан, когда нужно вмешаться именно в создание класса и остальных средств не хватает.
Где спотыкаются
Не могут объяснить разницу между __new__ метакласса и __init__ класса.
Тянут метакласс туда, где хватило бы декоратора или __init_subclass__.
Не знают про конфликт метаклассов при множественном наследовании.
Считают, что метакласс влияет на экземпляры. Он влияет на класс, экземпляры создаёт уже сам класс.