2014-10-07 74 views
6

我來自C#世界,所以我的看法可能有點偏斜。我期待在Python中使用DI,但是我注意到了一個圖書館的趨勢,他們似乎都依賴於服務定位器。也就是說,您必須將您的對象創建與框架綁定,例如injectlib.build(MyClass)才能獲得MyClass的實例。Python無需依賴服務定位器就可以完成DI嗎?

這裏是我的意思的例子 -

from injector import Injector, inject 


class Inner(object): 
    def __init__(self): 
     self.foo = 'foo' 


class Outer(object): 
    @inject(inner=Inner) 
    def __init__(self, inner=None): 
     if inner is None: 
      print('inner not provided') 
      self.inner = Inner() 
     else: 
      print('inner provided') 
      self.inner = inner 


injector = Injector() 

outer = Outer() 
print(outer.inner.foo) 

outer = injector.get(Outer) 
print(outer.inner.foo) 

有沒有在Python的方式來創建一個類,並自動推斷基於參數名稱的依賴類型?因此,如果我有一個名爲my_class的構造函數參數,那麼將會注入一個MyClass的實例。我想問的原因是我沒有看到如何將依賴注入到通過第三方庫自動創建的類中。

回答

6

要回答您明確提出的問題:no,Python中沒有內置的方法來自動從名爲my_class的參數獲取MyClass對象。這就是說,既沒有將你的對象創建綁定到框架上,也沒有提供給你的示例代碼看起來非常糟糕,這個問題總的來說有點令人困惑,因爲動態語言中的DI並不是什麼大不了的事情。

關於Python中關於DI的一般想法我會說this presentation給出了對不同方法的很好的概述。對於你的具體問題,我會根據你可能要做的事情給出兩個選項。

如果您想將DI添加到您自己的類中,我會在構造函數中使用具有默認值的參數,如演示文稿所示。例如:

import time 

class Example(object): 
    def __init__(self, sleep_func=time.sleep): 
     self.sleep_func = sleep_func 

    def foo(self): 
     self.sleep_func(10) 
     print('Done!') 

然後,你可以傳遞一個虛擬睡眠函數進行測試或其他。

如果你想通過DI,(不是我可以真正想象的用例,但看起來像你問的東西)操作圖書館的類,那麼我可能會猴子修補這些類到改變需要改變的東西。例如:

import test_module 

def dummy_sleep(*args, **kwargs): 
    pass 

test_module.time.sleep = dummy_sleep 
e = test_module.Example() 
e.foo() 
+1

很好的答案!在過去的幾個月裏,我一直在穩步地做Python,而不是像我從哪裏來(C#)那樣,Python確實不需要DI。事實上,我討厭混合兩者。 – 2015-07-20 12:16:18