Code前端首页关于Code前端联系我们

彻底理解Python依赖注入

terry 2年前 (2023-09-24) 阅读数 68 #后端开发
一文深入理解Python中的依赖注入

简介

依赖注入是软件工程中使用的一种设计模式,它允许对象在创建对象时向外部提供其依赖项,而不是您自己创建依赖项。换句话说,您不是在类上创建自己的依赖项,而是从外部将依赖项注入到类中。 一文深入理解Python中的依赖注入

为什么要使用成瘾注射?

添加依赖项的优点是提高软件设计的灵活性和模块化、提高可测试性并减少组件之间的耦合。通过将对象与其依赖关系解耦,可以更轻松地进行更改而不影响系统的其他部分。

假设您有一个依赖于数据库连接的类。如果在此类中创建数据库连接,则会在类和数据库之间创建紧密连接。这意味着对数据库连接的更改需要对类进行更改,从而使代码不太灵活且更难以维护。

通过依赖注入,可以将数据库连接从外部转移到类中,使代码更加模块化,更易于测试。这还允许用另一个实现替换数据库连接,例如与不同的数据库或外部 API 交互,而无需更改类本身。

使用 Python 添加依赖项

Python 是一种流行的编程语言,支持多种实现依赖项添加的方法。本文使用构造函数注入来演示这个概念。

构造函数注入涉及通过构造函数将依赖项传输到类。这允许类将依赖项存储为实例变量,使其可供其方法使用。

创建一个示例来展示其工作原理。首先定义 UserRepository 接口,该接口依赖于 UserService 类:

class UserService:
    def __init__(self, user_repository):
        self.user_repository = user_repository
    def get_user(self, user_id):
        return self.user_repository.get_user(user_id)

在此示例中,User❙User❙❓ 将 作为 放入其构造函数中UserRepository 对象。然后,它将 UserRepository 对象存储为实例变量,并在其 get_user 方法中使用它。

您可以通过添加 get_user 方法来定义其接口 UserRepository: : :

class InMemoryUserRepository(UserRepository):
    def __init__(self):
        self.users = {
            1: {"id": 1, "name": "Alice"},
            2: {"id": 2, "name": "Bob"},
            3: {"id": 3, "name": "Charlie"},
        }
    def get_user(self, user_id):
        return self.users.get(user_id, None)

这将创建一个简单的用户界面。 ory 各种 一切都是必须要实现的。在本例中,创建了类 UserRepository 的实现,称为 InMemoryUserRepository,它将用户信息存储在内存中:。 类,定义包含用户数据的字典,并实现 get_user 方法以通过 ID 检索用户。

最后,在主函数中,创建了InMemoryUserRepository的实例并作为UserService传递。然后在Get_user方法中调用userService方法,以根据ID检索用户:

if __name__ == "__main__":
    user_repository = InMemoryUserRepository()
    user_service = UserService(user_repository)
    user = user_service.get_user(1)

在此示例中,创建A♾实例❙❙,它实现了UserRepository 接口。然后创建 UserService 的实例,并将 InMemoryUserRepository 实例作为参数传递给其构造函数。最后,使用 get_user 方法调用 UserService 实例以通过 ID 检索用户。

添加构造函数可以轻松将 UserRepository 实现更改为不同的实现,例如与数据库或外部 API 交互的实现,而无需更改 ♷ 服务器 类本身。这使得代码更加灵活并且更易于维护。

以下是完整的 InMemoryUserRepository.py 文件:

from UserRepository import UserRepository
from UserService import UserService

class InMemoryUserRepository(UserRepository):
    def __init__(self):
        self.users = {
            1: {"id": 1, "name": "Alice"},
            2: {"id": 2, "name": "Bob"},
            3: {"id": 3, "name": "Charlie"},
        }

    def get_user(self, user_id):
        return self.users.get(user_id, None)

if __name__ == "__main__":
    user_repository = InMemoryUserRepository()
    user_service = UserService(user_repository)
    user = user_service.get_user(1)
    print(user.get("name"))

以下示例显示如何替换 InMemo❙Reposaseser❙ 实现。 ryUserRepository 实现:

import os
import sqlite3
from UserRepository import UserRepository
from UserService import UserService

class DatabaseUserRepository(UserRepository):
    def __init__(self, db_path):
        self.db_path = db_path

    def get_user(self, user_id):
        with sqlite3.connect(self.db_path) as conn:
            cursor = conn.cursor()
            cursor.execute("SELECT id, name FROM users WHERE id=?", (user_id,))
            row = cursor.fetchone()
            if row is None:
                return None
            return {"id": row[0], "name": row[1]}

if __name__ == "__main__":
    # 用`DatabaseUserRepository`来替换`InMemoryUserRepository`
    db_dir = "test"
    os.makedirs(db_dir, exist_ok=True)
    db_path = os.path.join(db_dir, "test.db")
    
    with sqlite3.connect(db_path) as conn:
        cursor = conn.cursor()
        cursor.execute("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)")
        cursor.execute('INSERT INTO users (id, name) VALUES (1, "Alice")')
        cursor.execute('INSERT INTO users (id, name) VALUES (2, "Bob")')
        cursor.execute('INSERT INTO users (id, name) VALUES (3, "Charlie")')
    
    user_repository = DatabaseUserRepository(db_path)
    user_service = UserService(user_repository)
    user = user_service.get_user(1)
    print(user["name"])

在本例中,os模块用于在当前工作目录中创建一个新目录“test”(如果该目录不存在)然而。 ,并通过连接目录路径和文件名“test.db”来创建SQLite数据库文件的路径。

然后连接数据库,创建用户表,并向表中添加测试数据。

最后,创建 DatabaseUserRepository 类的实例。参数db_path设置为测试数据库文件的路径。此实例用于创建 UserService 类。一个例子。然后使用

参数 1 以及要打印到控制台 的用户名称调用 UserServiceget_user()。

本文中的所有代码都可以在 Github 上找到:https://github.com/PythonCodeNemesis/Python_Dependancy_Injector_Demo

总结

依赖关系是一种模块化的添加,可以使软件设计更加高效。并且更容易测试。 Python提供了多种实现依赖注入的方法,包括本文介绍的构造函数注入。

使用依赖注入可以创建与依赖关系解耦的类,使代码更易于修改和维护。这还可以提高软件的整体质量,使其更能适应长期变化。

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门