彻底理解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 各种 一切都是必须要实现的。在本例中,创建了类 最后,在主函数中,创建了 在此示例中,创建A♾实例❙❙,它实现了 添加构造函数可以轻松将 以下是完整的 以下示例显示如何替换 在本例中, 然后连接数据库,创建用户表,并向表中添加测试数据。 最后,创建 本文中的所有代码都可以在 Github 上找到:https://github.com/PythonCodeNemesis/Python_Dependancy_Injector_Demo 依赖关系是一种模块化的添加,可以使软件设计更加高效。并且更容易测试。 Python提供了多种实现依赖注入的方法,包括本文介绍的构造函数注入。 使用依赖注入可以创建与依赖关系解耦的类,使代码更易于修改和维护。这还可以提高软件的整体质量,使其更能适应长期变化。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)
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
以及要打印到控制台 的用户名称调用 UserService
类 get_user()。
总结
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。