Skip to content

文章

依赖注入能让我成为更好的Python程序员吗?

2025年2月16日 • 5 分钟阅读

依赖注入能让我成为更好的Python程序员吗?

依赖注入是静态语言中的主流,但在Python中使用它有意义吗?它会让我成为更好的Python程序员吗?

等等,依赖注入到底是什么?

首先,让我们回答这个问题:什么是依赖注入(DI)?

依赖注入是一种模式,使用时将对象的构造移到类的外部。相反,类依赖于一个抽象。

在C#和Java等静态语言中,依赖注入被大量使用来减少耦合并促进测试。实际上,你会发现专门用于维护依赖关系及其相互关系的依赖注入框架。

依赖注入有两个主要目的:

首先,它通过依赖抽象来减少复杂性。

其次,依赖抽象允许将不同的实现(包括用于测试的模拟对象)传递到类或函数中。

让我用一些代码来演示:

# Before 
class User:
    def __init__(self):
        self.database = SqlServerDatabase()

    def get_details(self, user_id: int):
        self.database.get_user_details(user_id)

# After  
class User:
    def __init__(self, database: Database):
        self.database = database

    def get_details(self, user_id: int):
        self.database.get_user_details(user_id)

这是依赖注入最简单的形式。虽然概念很简单,但它的强大之处在于能够实现灵活的设计。

Before示例中,User类与SqlServerDatabase类紧密耦合。如果我们想测试User类,我们需要创建一个新的SqlServerDatabase实例。

After示例中,User类与Database抽象松散耦合。我们可以将Database抽象的不同实现传递给User类。

让我用一个实际示例来演示这种灵活性,展示我们如何在不同的数据库实现之间切换:

date_string = "2023-10-01"  # Example date string
date_format = "%Y-%m-%d"    # Input string format
birthday = datetime.strptime(date_string, date_format) 
turn_of_the_century = datetime.strptime('2000-01-01', date_format)

database = PostgresDatabase("")

if birthday < turn_of_the_century:
    database = SqlServerDatabase("")

user = User(database=database)
user.get_details(user_id=1)

在第6行(birthday < turn_of_the_century),依赖注入允许我们根据不同条件轻松交换实现。虽然这种灵活性对生产代码很有价值,但依赖注入最常见的用途之一,特别是在静态语言中,是在测试中。

这里有一个例子:

class UserTests(unittest.TestCase):
    def test_is_authenticated(self):
        database = MockDatabase('connection_string')
        
        is_authenticated = User(database).is_authenticated('user', 'pass')

        self.assertTrue(is_authenticated)

这是一个使用MockDatabase类的简单示例。在Python中,我们也可以使用内置的Mock类来实现相同的结果。

有趣的是,在我参与的Python项目中,依赖注入并没有被广泛使用。来自静态语言背景,我感到惊讶——这似乎违反直觉。

然而,这种有限采用是有原因的。Python的内置patch功能已经提供了出色的测试能力,消除了依赖注入的主要好处之一。虽然依赖注入仍然可以帮助减少复杂性,但Python有其他方法来实现相同的目标。

我并不是说不应该在Python中使用依赖注入。恰恰相反,像所有工具和模式一样,有使用它们的地方和时机。依赖注入只是你工具箱中的另一个工具,它将提高你代码的质量。

我认为依赖注入通常会提高大多数Python项目的代码质量。

如果你有兴趣进一步探索依赖注入,我建议查看两个流行的Python框架:

  • Injector (github.com/python-injector/injector)
  • Dependency Injector (python-dependency-injector.ets-labs.org)

作者:Chuck Conway 专注于软件工程和生成式人工智能。在社交媒体上与他联系:X (@chuckconway) 或访问他的 YouTube

↑ 回到顶部

您可能还喜欢