Ответ
В Python внедрение зависимостей (Dependency Injection) можно реализовать несколькими способами без привлечения специализированных фреймворков, следуя принципу "явное лучше неявного".
-
Через конструктор (Constructor Injection) Это самый распространенный и предпочтительный способ. Зависимости передаются как аргументы в метод
__init__.class DatabaseClient: def query(self, sql: str) -> list: # ... логика запроса к БД return [{"id": 1}] class UserService: def __init__(self, db_client: DatabaseClient): self._db_client = db_client def get_user(self, user_id: int): return self._db_client.query(f"SELECT * FROM users WHERE id={user_id}") # Явное внедрение зависимости при создании объекта db = DatabaseClient() user_service = UserService(db_client=db) -
Через метод (Method/Setter Injection) Зависимость передается через отдельный метод уже после создания объекта. Менее предпочтителен, так как объект может находиться в невалидном состоянии до вызова сеттера.
class ReportGenerator: _formatter = None def set_formatter(self, formatter): self._formatter = formatter def generate(self, data): if not self._formatter: raise ValueError("Formatter not set") return self._formatter.format(data) -
Через фабричную функцию Функция или метод, который инкапсулирует логику создания объекта и его зависимостей.
def create_user_service() -> UserService: db_client = DatabaseClient() return UserService(db_client=db_client) # Использование user_service = create_user_service()
Основной принцип — инверсия контроля (IoC): класс не создает свои зависимости сам, а получает их извне. Это упрощает тестирование (можно подменить реальную БД на mock-объект) и повышает модульность кода.