Приходилось ли писать или видеть метаклассы в Python вживую
Что проверяют
Знаете ли вы, как в Python устроено создание классов, и хватает ли у вас вкуса не тащить метакласс туда, где хватит механизма попроще. Ответ «видел в библиотеках, сам не писал» здесь совершенно нормальный, если вы понимаете, что именно видели.
Как отвечать
Сформулируйте суть: класс в Python это объект, и создаёт его метакласс, по умолчанию type. Метакласс вмешивается в момент объявления класса, а не в момент создания экземпляра, через __new__ и __init__, и может изменить пространство имён, проверить его или зарегистрировать класс где-то ещё.
Дальше самое ценное это назвать, где они встречаются вживую:
- описание моделей в ORM: атрибуты превращаются в поля, класс попадает в реестр;
- библиотеки валидации данных, которые собирают схему из аннотаций;
- абстрактные базовые классы и перечисления в стандартной библиотеке.
И сразу про альтернативы, это отличает опытного от начитавшегося. Нужно поймать наследников, есть __init_subclass__. Нужно узнать имя атрибута в классе, есть __set_name__ у дескриптора. Нужно дописать класс после объявления, подойдёт декоратор класса. Метакласс оправдан, когда требуется вмешаться именно в построение класса, например подменить словарь пространства имён.
Хороший финал: в прикладном коде я предпочитаю обойтись без метаклассов, потому что читает такой код не только автор.
Где спотыкаются
Путают уровни. __new__ метакласса вызывается при создании класса, __new__ класса при создании экземпляра. Пока это не разделено, объяснение расползается, и человек не может сказать, что вернёт type(MyClass).
Не знают про конфликт метаклассов. Наследование от двух классов с разными метаклассами падает ошибкой ещё на импорте, и это частая причина, по которой чужие библиотеки не смешиваются между собой.
Приводят как единственный пример одиночку и на этом останавливаются. Задача решается модульной переменной или функцией с кэшем, а метакласс здесь только усложняет тесты: подменить такой объект в тесте тяжело.