Ответ
Метакласс в Python — это "класс для классов". Если обычный класс определяет, как создаются и ведут себя объекты (экземпляры), то метакласс определяет, как создаются и ведут себя сами классы.
По умолчанию метаклассом для всех классов является type. Чтобы создать свой, нужно унаследовать класс от type и переопределить его метод __new__ или __init__.
Пример: Метакласс, добавляющий атрибут created_at ко всем классам
import time
# 1. Создаем метакласс, наследуясь от type
class TimestampMeta(type):
# 2. Переопределяем __new__
# Этот метод вызывается при создании нового КЛАССА
def __new__(cls, name, bases, namespace):
# Добавляем новый атрибут в пространство имен будущего класса
namespace['created_at'] = time.ctime()
print(f"Создание класса '{name}' с метаклассом TimestampMeta...")
# Вызываем __new__ родительского класса (type) для завершения создания
return super().__new__(cls, name, bases, namespace)
# 3. Применяем метакласс к нашему классу
class MyModel(metaclass=TimestampMeta):
def __init__(self):
self.data = "some data"
# Проверяем, что атрибут был добавлен в класс
print(MyModel.created_at)
# > Создание класса 'MyModel' с метаклассом TimestampMeta...
# > [текущее время, например, 'Mon Dec 18 15:30:00 2023']
Разбор метода __new__:
cls: Сам метакласс (TimestampMeta).name: Имя создаваемого класса в виде строки ('MyModel').bases: Кортеж родительских классов ((object,)).namespace: Словарь, содержащий все атрибуты и методы, определенные в теле класса ({'__init__': <function...>, '__module__': ...}). Мы можем изменять этот словарь перед созданием класса.
Основные сценарии использования:
- Автоматическая регистрация: Регистрация плагинов или моделей в реестре (как в Django ORM).
- Валидация: Проверка, что создаваемый класс соответствует определенным правилам (например, имеет нужные методы).
- Инъекция атрибутов: Автоматическое добавление логгеров, полей или методов в классы.