在Java中,IoC / DI是一种非常常见的实践,广泛应用于web应用程序、几乎所有可用的框架和Java EE中。另一方面,也有很多大型的Python web应用程序,但除了Zope(我听说它的编码真的很糟糕)之外,IoC在Python世界中似乎并不常见。(如果你认为我是错的,请举一些例子)。

当然,有一些流行的Java IoC框架的克隆可用于Python,例如springpython。但它们似乎都没有被实际使用。至少,我从来没有碰到过Django或sqlalchemy+<插入您最喜欢的wsgi工具箱在这里>的基于web应用程序使用类似的东西。

在我看来,IoC有合理的优势,可以很容易地取代django-default-user-model,但在Python中广泛使用接口类和IoC看起来有点奇怪,而且不»pythonic«。但是也许有人有更好的解释,为什么IoC在Python中没有被广泛使用。


当前回答

我支持“Jörg W Mittag”的回答:“DI/IoC的Python实现是如此的轻量级,以至于它完全消失了”。

为了支持这一说法,看看Martin Fowler从Java移植到Python的著名示例:Python:Design_Patterns:Inversion_of_Control

从上面的链接中可以看到,Python中的“Container”可以用8行代码编写:

class Container:
    def __init__(self, system_data):
        for component_name, component_class, component_args in system_data:
            if type(component_class) == types.ClassType:
                args = [self.__dict__[arg] for arg in component_args]
                self.__dict__[component_name] = component_class(*args)
            else:
                self.__dict__[component_name] = component_class

其他回答

IoC/DI是一个设计概念,但不幸的是,它经常被认为是一个适用于某些语言(或类型系统)的概念。我希望看到依赖注入容器在Python中变得更加流行。有Spring,但它是一个超级框架,似乎是Java概念的直接移植,没有太多考虑“Python方式”。

鉴于Python 3中的注释,我决定尝试一个功能齐全但简单的依赖注入容器:https://github.com/zsims/dic。它基于。net依赖注入容器的一些概念(如果你曾经在那个领域玩过,IMO是很棒的),但与Python概念发生了变化。

我支持“Jörg W Mittag”的回答:“DI/IoC的Python实现是如此的轻量级,以至于它完全消失了”。

为了支持这一说法,看看Martin Fowler从Java移植到Python的著名示例:Python:Design_Patterns:Inversion_of_Control

从上面的链接中可以看到,Python中的“Container”可以用8行代码编写:

class Container:
    def __init__(self, system_data):
        for component_name, component_class, component_args in system_data:
            if type(component_class) == types.ClassType:
                args = [self.__dict__[arg] for arg in component_args]
                self.__dict__[component_name] = component_class(*args)
            else:
                self.__dict__[component_name] = component_class

部分原因是模块系统在Python中的工作方式。你可以免费获得一种“单例”,只需从模块中导入它。在模块中定义一个对象的实际实例,然后任何客户端代码都可以导入它,并实际获得一个工作的、完全构造/填充的对象。

这与Java相反,在Java中不导入对象的实际实例。这意味着你总是必须自己实例化它们(或使用某种IoC/DI风格的方法)。您可以通过使用静态工厂方法(或实际的工厂类)来减轻必须自己实例化所有东西的麻烦,但这样您仍然会产生每次实际创建新方法的资源开销。

IoC容器主要使用**kwarg来“模仿”

class A:
    def __init__(self, **kwargs):
        print(kwargs)

Class B:
    pass

Class C:
    pass

Ainstance = A(b=B, c=C)

Haven't used Python in several years, but I would say that it has more to do with it being a dynamically typed language than anything else. For a simple example, in Java, if I wanted to test that something wrote to standard out appropriately I could use DI and pass in any PrintStream to capture the text being written and verify it. When I'm working in Ruby, however, I can dynamically replace the 'puts' method on STDOUT to do the verify, leaving DI completely out of the picture. If the only reason I'm creating an abstraction is to test the class that's using it (think File system operations or the clock in Java) then DI/IoC creates unnecessary complexity in the solution.