2014-10-07 16 views
6

Vengo dal mondo C#, quindi le mie visualizzazioni potrebbero essere leggermente distorte. Sto cercando di fare DI in Python, tuttavia sto notando una tendenza con le librerie in cui sembrano fare affidamento su un localizzatore di servizi. Cioè, devi legare la creazione dell'oggetto al framework, ad esempio injectlib.build(MyClass) per ottenere un'istanza di MyClass.Can Python può fare perfettamente senza fare affidamento su un localizzatore di servizi?

Ecco un esempio di ciò che intendo -

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) 

C'è un modo in Python per creare una classe, mentre inferire automaticamente i tipi di dipendenza basato sui nomi dei parametri? Quindi, se ho un parametro costruttore chiamato my_class, verrà iniettata un'istanza di MyClass. La ragione che chiedo è che non vedo come potrei iniettare una dipendenza in una classe che viene creata automaticamente tramite una libreria di terze parti.

risposta

6

Per rispondere alla domanda che hai chiesto esplicitamente: no, non esiste un modo integrato in Python per ottenere automaticamente un oggetto MyClass da un parametro denominato my_class.

Detto questo, né "legare la creazione dell'oggetto alla struttura" né il codice di esempio che hai dato sembrano terribilmente pitonici, e questa domanda in generale è un po 'confusa perché DI in lingue dinamiche non è davvero un grosso problema.

Per considerazioni generali su DI in Python, direi che this presentation offre una buona panoramica dei diversi approcci. Per la tua domanda specifica, darò due opzioni in base a ciò che potresti provare a fare.

Se si sta tentando di aggiungere DI alle proprie classi, vorrei utilizzare i parametri con i valori predefiniti nel costruttore, come mostra quella presentazione. E.g:

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!') 

E quindi è possibile passare in una funzione di sonno fittizio per test o qualsiasi altra cosa.

Se si sta tentando di manipolare le classi di una libreria tramite DI, (non è qualcosa che posso davvero immaginare per un caso d'uso, ma sembra quello che stai chiedendo) allora probabilmente mi limito ad applicare patch a quelle classi per cambia tutto ciò che è necessario cambiare. E.g:

import test_module 

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

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

Ottima risposta! Sono d'accordo ora dopo aver fatto Python costantemente negli ultimi mesi che, a differenza di dove provengo (C#), Python non richiede realmente DI. In effetti, odiavo mescolare i due. –

Problemi correlati