Kon*_*rin 12 python design-patterns dependency-injection
我最近一直在阅读很多关于python-way的内容,所以我的问题是
如何做依赖注入python-way?
我正在谈论通常的情况,例如,服务A需要访问UserService以进行授权检查.
Tho*_*ers 14
这一切都取决于具体情况.例如,如果您使用依赖注入进行测试 - 因此您可以轻松地模拟某些东西 - 您通常可以完全放弃注入:您可以模拟出您注入的模块或类:
subprocess.Popen = some_mock_Popen
result = subprocess.call(...)
assert some_mock_popen.result == result
Run Code Online (Sandbox Code Playgroud)
subprocess.call()将调用subprocess.Popen(),我们可以模拟它,而不必以特殊的方式注入依赖.我们可以直接替换subprocess.Popen.(这只是一个例子;在现实生活中,你会以更加健壮的方式做到这一点.)
如果对更复杂的情况使用依赖注入,或者模拟整个模块或类是不合适的(例如,因为你只想模拟一个特定的调用)那么通常使用类属性或模块全局变量用于依赖选择.例如,考虑一个my_subprocess.py:
from subprocess import Popen
def my_call(...):
return Popen(...).communicate()
Run Code Online (Sandbox Code Playgroud)
您可以轻松替换分配给的Popen呼叫; 它不会影响任何其他调用(当然它会替换所有调用.)同样,类属性:my_call()my_subprocess.Popensubprocess.Popenmy_subprocess.Popen
class MyClass(object):
Popen = staticmethod(subprocess.Popen)
def call(self):
return self.Popen(...).communicate(...)
Run Code Online (Sandbox Code Playgroud)
当使用这样的类属性时,考虑到选项很少需要,你应该小心使用staticmethod.如果不这样做,并且您要插入的对象是普通函数对象或其他类型的描述符(如属性),从类或实例中检索时会执行某些特殊操作,它会执行错误的操作.更糟糕的是,如果您使用的东西现在不是描述符(如subprocess.Popen示例中的类),它现在可以工作,但如果有问题的对象在未来改变为正常函数,它将会混乱.
最后,只有简单的回调; 如果您只想将类的特定实例绑定到特定服务,则可以将服务(或一个或多个服务的方法)传递给类初始化程序,并让它使用:
class MyClass(object):
def __init__(self, authenticate=None, authorize=None):
if authenticate is None:
authenticate = default_authenticate
if authorize is None:
authorize = default_authorize
self.authenticate = authenticate
self.authorize = authorize
def request(self, user, password, action):
self.authenticate(user, password)
self.authorize(user, action)
self._do_request(action)
...
helper = AuthService(...)
# Pass bound methods to helper.authenticate and helper.authorize to MyClass.
inst = MyClass(authenticate=helper.authenticate, authorize=helper.authorize)
inst.request(...)
Run Code Online (Sandbox Code Playgroud)
在设置类似的实例属性时,您永远不必担心触发描述符,因此只需分配函数(或类或其他callables或实例)就可以了.
| 归档时间: |
|
| 查看次数: |
7259 次 |
| 最近记录: |