在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
实际上,使用DI编写足够干净和紧凑的代码是相当容易的(我想知道,它会/保持python化吗,但无论如何:)),例如,我实际上更喜欢这种编码方式:
def polite(name_str):
return "dear " + name_str
def rude(name_str):
return name_str + ", you, moron"
def greet(name_str, call=polite):
print "Hello, " + call(name_str) + "!"
_
>>greet("Peter")
Hello, dear Peter!
>>greet("Jack", rude)
Hello, Jack, you, moron!
是的,这可以被看作是参数化函数/类的一种简单形式,但它确实起作用了。所以,也许Python默认包含的电池在这里也足够了。
另外,我还发布了一个更大的例子,说明了这种简单的方法在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()
你可以手动使用Python进行依赖注入,但手动方法有其缺点:
大量的样板代码来进行连接。你可以使用Python的动态特性来进行注入,但这样你就失去了IDE的支持(例如,PyCharm中的Ctrl+Space),并且你会使代码更难理解和调试
没有标准:每个程序员都有自己解决相同问题的方法,这导致了重新发明轮子,理解彼此的代码很快就会成为一种痛苦。依赖注入库为插件提供了简单的框架
要做到这一切,我们需要一个依赖注入框架,例如这个https://python-dependency-injector.ets-labs.org/index.html似乎是Python最成熟的依赖注入框架。
对于较小的应用程序,DI容器是不必要的,对于任何有几百行代码或更多的东西,DI容器是必须的,以保持你的代码可维护性。