Что такое метакласс и когда он действительно нужен?
- Что такое type в Python?
- Чем метакласс отличается от декоратора класса и __init_subclass__?
Класс — тоже объект, а метакласс — класс класса: он управляет созданием классов. По умолчанию это type. Метакласс нужен редко: регистрация подклассов и проверка их структуры обычно решаются __init_subclass__ или декоратором класса, они проще.
- type(name, bases, dict) создаёт класс динамически
- Реальные метаклассы: ABCMeta, EnumMeta, модели Django и SQLAlchemy
- Конфликт метаклассов при множественном наследовании — частая боль
А ещё «Если вы сомневаетесь, нужен ли метакласс, — он не нужен» (Тим Питерс)
Подробно
Как создаётся класс. Инструкция class выполняет тело класса, собирает пространство имён и вызывает метакласс: Meta(name, bases, namespace). Результат — объект класса.
class Registry(type):
classes = {}
def __new__(mcs, name, bases, ns):
cls = super().__new__(mcs, name, bases, ns)
mcs.classes[name] = cls
return cls
class Plugin(metaclass=Registry): ...
Что умеет метакласс: менять пространство имён до создания класса (__prepare__), проверять или переписывать атрибуты, управлять isinstance (__instancecheck__ в ABCMeta), перехватывать вызов класса (__call__ — например, синглтон).
Лёгкие альтернативы:
class Plugin:
registry = {}
def __init_subclass__(cls, **kw):
super().__init_subclass__(**kw)
Plugin.registry[cls.__name__] = cls
Декоратор класса — для изменения одного класса; __init_subclass__ (Python 3.6) — для реакции на наследников; дескрипторы с __set_name__ — для полей.
Где метаклассы оправданы: фреймворки с декларативным синтаксисом (ORM-модели, Enum), где нужен контроль над созданием класса целиком.
Что хотят услышать
- Метакласс как класс класса, type.
- Когда вызывается.
- Альтернативы и почему они предпочтительнее.
Проверьте себя
Один верный вариант. Подумайте, потом откройте ответ.
Показать варианты и ответ
- ✗Метакласс — абстрактный базовый класс, от которого обязаны наследоваться все классы с методами
- ✓Класс класса, по умолчанию type; обычно его заменяют __init_subclass__ или декоратор класса
- ✗В Python нельзя создать класс динамически
- ✗Метакласс — то же самое, что миксин
Разбор темы
- ООП в Python — классы, свойства, наследование и dataclass
self и __init__, магические методы, property, staticmethod и classmethod, MRO и super, dataclass против namedtuple и Pydantic, ABC и Protocol, метаклассы.
Связанные вопросы
Разбор собеседования с sotto
После собеседования sotto разбирает разговор: оценка, каждый вопрос — хорошо, частично или слабо, чего не хватило в ответе и над чем поработать к следующему разу. Первые 30 минут бесплатно.