ДЗ 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-типы |
|---|---|
| 0 | IntField, StringField, DateField, BoolField |
| 1 | FloatField, ListField, EmailField, ChoiceField |
| 2 | IntField, 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)отличается отclassstatement
type() — это то, как Python создаёт классы на самом деле. Понимание этого механизма закрывает картину метапрограммирования целиком.
Итого
| Задача | Баллы |
|---|---|
| 7.1 Мини-ORM на метаклассах | 4 |
| 7.2 make_dataclass через type() | 2 |
| Итого | 6 |