Магия.
Нет, действительно.
Классы Python не имеют встроенной структуры, как на C ++. Они сами, просто объекты - экземпляры другого типа:
class Foo(object):
pass
print(type(Foo)) # <class 'type'>
Вы даже можете сделать класс, как если бы вы сделали любой другой объект, вызвав type
. Это:
class Bar(object):
a = 1
b = 2
Действительно (более или менее) синтаксический сахар для этого:
Bar = type('Bar', (object,), {'a': 1, 'b': 2})
type
берет имя вашего нового класса, список его суперклассов , и dict всех атрибутов класса и выплескивает новый класс.
Но, поскольку type
- это просто класс, как любой другой, возможно подкласс и придать ему другое поведение. И это то, что сделал Django: он создал подкласс type
, который делает что-то другое с атрибутом атрибутов, которые вы ему передаете.
Вы не видите, что это происходит непосредственно в вашем собственном коде, но если вы проверите type(models.Model)
, вы узнаете, что его тип не type
, а что-то особенное для Django. Вероятно, он имеет «мета» в названии, потому что он называется метаклассом : классом класса.
Это довольно распространенный шаблон для создания «декларативных» библиотек в Python , где атрибуты класса фактически определяют некоторую структуру. Вы можете видеть то же самое в валидации формы (wtforms), валидации схемы (дуршлаг), других ORM (sqlalchemy) и даже модуле перечисления stdlib.