Метаклассы и ABC
Управление тем, как строятся и ведут себя сами классы
__init_subclass__; написанный вручную метакласс — это тяжёлая артиллерия, к которой прибегают редко и обдуманно.
- объяснить цепочку экземпляр -> класс -> метакласс и почему
typeнаходится на вершине, - создавать класс динамически с помощью
type(name, bases, namespace), - использовать
__init_subclass__для перехвата создания подкласса без метакласса, - определять и обеспечивать интерфейс с помощью
abc.ABCи@abstractmethod, - писать собственный метакласс и, что важнее всего, оценивать, когда он действительно оправдан.
1. Класс тоже объект
Вы уже знаете, что каждое значение в Python — это объект со своим типом: type(3) — это int, type("hi") — это str. Шаг, который упускают большинство разработчиков, состоит в том, что это относится и к самим классам. Класс — это объект времени выполнения, и его тип называется метаклассом. По умолчанию этот метакласс — встроенный type.
class Dog:
pass
fido = Dog()
print(type(fido)) # <class '__main__.Dog'>
print(type(Dog)) # <class 'type'>
print(type(type)) # <class 'type'> -- type -- сам себе тип
Итак, есть цепочка: экземпляр является экземпляром класса, а класс является экземпляром метакласса. Поскольку Dog сам является объектом, вы можете присвоить его переменной, поместить в список, добавить к нему атрибуты и — ключевое озарение — можете построить его программно, а не с помощью ключевого слова class.