Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Базовая модель (Base Model)
Базовая модель (Base Model, или базовый класс) — это родительский класс, от которого наследуются другие классы. Базовая модель определяет общие свойства и методы, которые используются всеми дочерними классами. Это фундаментальная концепция объектно-ориентированного программирования (ООП) и архитектуры приложений.
Что такое базовая модель?
# Без базовой модели — дублирование кода
class User:
def __init__(self, id, name):
self.id = id
self.name = name
def save(self):
print(f"Saving user {self.name}")
def delete(self):
print(f"Deleting user {self.name}")
class Product:
def __init__(self, id, name):
self.id = id
self.name = name
def save(self):
print(f"Saving product {self.name}")
def delete(self):
print(f"Deleting product {self.name}")
# Много дублирования!
Решение: базовая модель
# Один раз определяем общую логику
class BaseModel:
def __init__(self, id, name):
self.id = id
self.name = name
def save(self):
print(f"Saving {self.__class__.__name__} {self.name}")
def delete(self):
print(f"Deleting {self.__class__.__name__} {self.name}")
# Дочерние классы наследуют базовую логику
class User(BaseModel):
pass
class Product(BaseModel):
pass
# Используем
user = User(1, "Alice")
user.save() # Saving User Alice
product = Product(2, "Laptop")
product.delete() # Deleting Product Laptop
Pydantic BaseModel
В современном Python часто используется Pydantic BaseModel для валидации данных:
from pydantic import BaseModel, EmailStr, Field
from typing import Optional
# Базовая модель в Pydantic
class User(BaseModel):
id: int
name: str
email: EmailStr
age: Optional[int] = None
# Автоматическая валидация
user = User(
id=1,
name="Alice",
email="alice@example.com",
age=30
)
# JSON сериализация
print(user.model_dump()) # {'id': 1, 'name': 'Alice', ...}
print(user.model_dump_json()) # JSON строка
# Валидация при создании
try:
invalid_user = User(
id=1,
name="Alice",
email="not-an-email", # Ошибка!
age=30
)
except ValueError as e:
print(f"Validation error: {e}")
Пример: ORM модели
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
from sqlalchemy import String, Integer, DateTime, func
from datetime import datetime, UTC
# Базовая модель для всех таблиц
class Base(DeclarativeBase):
pass
# Общие поля для всех моделей
class TimestampedModel(Base):
__abstract__ = True # Не создаёт таблицу, только наследуется
id: Mapped[int] = mapped_column(primary_key=True)
created_at: Mapped[datetime] = mapped_column(default=lambda: datetime.now(UTC))
updated_at: Mapped[datetime] = mapped_column(default=lambda: datetime.now(UTC), onupdate=func.now())
# Дочерние модели
class User(TimestampedModel):
__tablename__ = 'users'
name: Mapped[str] = mapped_column(String(100))
email: Mapped[str] = mapped_column(String(100), unique=True)
class Product(TimestampedModel):
__tablename__ = 'products'
title: Mapped[str] = mapped_column(String(200))
price: Mapped[float]
# Все модели имеют id, created_at, updated_at автоматически
Пример: Domain Model (DDD)
from datetime import datetime
from enum import Enum
from uuid import UUID
# Базовая модель для всех domain сущностей
class DomainModel:
def __init__(self, id: UUID):
self.id = id
self.version = 0 # Для optimistic locking
self.created_at = datetime.now()
def mark_as_changed(self):
self.version += 1
class UserStatus(Enum):
ACTIVE = "active"
BLOCKED = "blocked"
DELETED = "deleted"
class User(DomainModel):
def __init__(self, id: UUID, email: str, name: str):
super().__init__(id)
self.email = email
self.name = name
self.status = UserStatus.ACTIVE
self.orders = []
def block(self):
self.status = UserStatus.BLOCKED
self.mark_as_changed()
def add_order(self, order):
self.orders.append(order)
self.mark_as_changed()
class Order(DomainModel):
def __init__(self, id: UUID, user_id: UUID, total: float):
super().__init__(id)
self.user_id = user_id
self.total = total
self.status = "pending"
def complete(self):
self.status = "completed"
self.mark_as_changed()
Пример: API Response Model
from pydantic import BaseModel, ConfigDict
from typing import Generic, TypeVar
T = TypeVar('T')
# Базовая модель для всех API ответов
class BaseResponse(BaseModel):
success: bool
message: str
model_config = ConfigDict(from_attributes=True)
class PaginatedResponse(BaseResponse, Generic[T]):
data: list[T]
total: int
page: int
per_page: int
total_pages: int
# Использование
class UserDTO(BaseModel):
id: int
name: str
email: str
users_response = PaginatedResponse[
response = PaginatedResponse[
UserDTO
](
success=True,
message="Users fetched successfully",
data=[
UserDTO(id=1, name="Alice", email="alice@example.com"),
UserDTO(id=2, name="Bob", email="bob@example.com"),
],
total=2,
page=1,
per_page=10,
total_pages=1
)
Пример: Repository Pattern
from abc import ABC, abstractmethod
from typing import Generic, TypeVar, List
T = TypeVar('T')
ID = TypeVar('ID')
# Базовая модель для всех репозиториев
class BaseRepository(ABC, Generic[T, ID]):
@abstractmethod
def get(self, id: ID) -> T:
"""Get entity by id"""
pass
@abstractmethod
def get_all(self) -> List[T]:
"""Get all entities"""
pass
@abstractmethod
def save(self, entity: T) -> T:
"""Save entity"""
pass
@abstractmethod
def delete(self, id: ID) -> None:
"""Delete entity"""
pass
# Реализация для User
class UserRepository(BaseRepository[User, int]):
def __init__(self, db):
self.db = db
def get(self, id: int) -> User:
return self.db.query(User).filter(User.id == id).first()
def get_all(self) -> List[User]:
return self.db.query(User).all()
def save(self, entity: User) -> User:
self.db.add(entity)
self.db.commit()
return entity
def delete(self, id: int) -> None:
user = self.get(id)
self.db.delete(user)
self.db.commit()
Лучшие практики базовых моделей
1. DRY принцип (Don't Repeat Yourself)
# ❌ Плохо — дублирование
class User:
def validate(self): pass
def to_dict(self): pass
class Product:
def validate(self): pass
def to_dict(self): pass
# ✅ Хорошо — одна базовая модель
class BaseModel:
def validate(self): pass
def to_dict(self): pass
2. Не переусложняй
# ❌ Плохо — слишком абстрактно
class VeryGenericBase:
def do_something_abstract(self): pass
def do_another_thing(self): pass
# ✅ Хорошо — конкретные методы
class Model:
def validate(self): pass
def save(self): pass
3. Используй composition вместо наследования
# ❌ Плохо — глубокое наследование
class A:
pass
class B(A):
pass
class C(B):
pass
# ✅ Хорошо — composition
class Timestamps:
created_at: datetime
updated_at: datetime
class Model:
timestamps: Timestamps
Резюме
Базовая модель — это родительский класс, определяющий общую функциональность:
- Что это: класс, от которого наследуются другие классы
- Зачем: избежать дублирования кода, определить общий интерфейс
- Примеры: Pydantic BaseModel, SQLAlchemy Base, Abstract Base Classes
- В архитектуре: используется в DDD, Repository Pattern, API Design
- Правило: SOLID принципы, не переусложняй, используй composition
Хорошо спроектированные базовые модели делают код чище, понятнее и проще в поддержке.