Перейти к основному содержимому

ДЗ 7 — Метапрограммирование

📚 Лекция: Метапрограммирование

Тема и дедлайн

Тема курса: модуль 8 (метапрограммирование) Дедлайн: 7 мая 2026, 23:59 Classroom: Принять задание


7.1 — Мини-ORM на метаклассах (4 балла) ★★★

Реализуй декларативную систему описания моделей данных в стиле Django ORM — но без базы данных.

Что нужно реализовать:

class User(Model):
name = StringField(max_length=50)
age = IntField(min_value=0, max_value=150)
email = StringField()

# Создание
user = User(name="Alice", age=30, email="alice@example.com")

# Валидация
user.validate() # OK
user.age = -1
user.validate() # ValueError: age must be >= 0

# Сериализация
user.to_dict() # {"name": "Alice", "age": 30, "email": "..."}
User.from_dict({...}) # создание из словаря

# Наследование
class Admin(User):
level = IntField(min_value=1, max_value=10)

# Admin._fields содержит name, age, email, level

Компоненты системы:

  • Field — базовый дескриптор. Реализует __set_name__, __get__, __set__.
  • ModelMeta(type) — метакласс. При создании класса собирает все Field-экземпляры в cls._fields. Поддерживает наследование: поля родителя попадают в _fields потомка.
  • Model — базовый класс (metaclass=ModelMeta). Реализует __init__, validate, to_dict, from_dict, __repr__.

Твой вариант определяет набор Field-типов (реализуй все из своего набора):

#Field-типы
0IntField, StringField, DateField, BoolField
1FloatField, ListField, EmailField, ChoiceField
2IntField, StringField, ForeignKeyField, JSONField

Требования к Field-типам:

  • Каждый тип валидирует соответствующий Python-тип при записи (TypeError)
  • Поддерживает специфичные ограничения (max_length, min_value, choices...)
  • Поднимает ValueError при нарушении ограничений
Зачем это

Метаклассы — финальный уровень понимания ООП в Python. Именно так устроены Django Models, SQLAlchemy, Pydantic. После этого задания ты будешь понимать что происходит «под капотом» этих библиотек.


7.2 — Динамическое создание классов через type() (2 балла) ★★★

Реализуй функцию make_dataclass(), которая динамически создаёт класс — аналог @dataclass, но через type() напрямую.

Point = make_dataclass("Point", {"x": float, "y": float})

p = Point(x=1.0, y=2.0)
print(p) # Point(x=1.0, y=2.0)
p == Point(x=1.0, y=2.0) # True
p == Point(x=9.0, y=2.0) # False

Требования:

  • __init__ — принимает все поля как keyword arguments
  • __repr__ClassName(field=value, ...)
  • __eq__ — сравнение по значениям всех полей
  • Реализация через type(name, bases, namespace) — без dataclasses, без attrs
  • В комментарии: объясни чем type(name, bases, dict) отличается от class statement
Зачем это

type() — это то, как Python создаёт классы на самом деле. Понимание этого механизма закрывает картину метапрограммирования целиком.


Итого

ЗадачаБаллы
7.1 Мини-ORM на метаклассах4
7.2 make_dataclass через type()2
Итого6