在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中没有被广泛使用。


当前回答

我认为由于python的动态特性,人们并不经常看到对另一个动态框架的需求。当一个类继承了new-style 'object'时,你可以动态地创建一个新变量(https://wiki.python.org/moin/NewClassVsClassicClass)。

即。 在普通python中:

#application.py
class Application(object):
    def __init__(self):
        pass

#main.py
Application.postgres_connection = PostgresConnection()

#other.py
postgres_connection = Application.postgres_connection
db_data = postgres_connection.fetchone()

不过,看看https://github.com/noodleflake/pyioc,这可能就是你要找的。

即pyioc

from libs.service_locator import ServiceLocator

#main.py
ServiceLocator.register(PostgresConnection)

#other.py
postgres_connection = ServiceLocator.resolve(PostgresConnection)
db_data = postgres_connection.fetchone()

其他回答

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

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.

IoC和DI在成熟的Python代码中非常常见。由于鸭子类型,您不需要框架来实现依赖注入。

最好的例子是如何使用settings.py设置Django应用程序:

# settings.py
CACHES = {
    'default': {
        'BACKEND': 'django_redis.cache.RedisCache',
        'LOCATION': REDIS_URL + '/1',
    },
    'local': {
        'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
        'LOCATION': 'snowflake',
    }
}

Django Rest Framework充分利用了DI:

class FooView(APIView):
    # The "injected" dependencies:
    permission_classes = (IsAuthenticated, )
    throttle_classes = (ScopedRateThrottle, )
    parser_classes = (parsers.FormParser, parsers.JSONParser, parsers.MultiPartParser)
    renderer_classes = (renderers.JSONRenderer,)

    def get(self, request, *args, **kwargs):
        pass

    def post(self, request, *args, **kwargs):
        pass

让我提醒一下(来源):

“依赖注入”是一个5美分概念的25美元术语。[…依赖注入意味着给一个对象它的实例变量。[…]。

不像Java中的强类型。Python的duck类型行为使得传递对象非常容易。

Java开发人员专注于构造类结构和对象之间的关系,同时保持灵活性。IoC对于实现这一目标非常重要。

Python开发人员专注于完成工作。他们只是在需要的时候把类连接起来。他们甚至不用担心课程的类型。只要它会嘎嘎叫,它就是鸭子!这种性质没有给国际奥委会留下任何余地。