Can Python do DI without problems without relying on a service locator?

I come from the C # world, so my views may be slightly distorted. I am looking for DI in Python, however I notice a trend with libraries where they all rely on a service locator. That is, you must associate the creation of an object with a framework, for example injectlib.build(MyClass) , to get an instance of MyClass .

Here is an example of what I mean -

 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) 

Is there a way in Python to create a class by automatically detecting dependency types based on parameter names? Therefore, if I have a constructor parameter named my_class , then an instance of MyClass will be introduced. The reason I'm asking for is because I don’t see how I can put the dependency in a class that is created automatically through a third-party library.

+6
source share
1 answer

To answer the question that you explicitly asked: no, there is no built-in way in Python to automatically get the MyClass object from a parameter named my_class.

However, neither “binding your object creation to the framework” nor the example code you gave look awful Pythonic, and this question is generally quite confusing because DI in dynamic languages ​​is not a big problem.

For general thoughts on DI in Python, I would say this presentation gives a pretty good overview of the various approaches. For your specific question, I will give two options based on what you can try to do.

If you are trying to add DI to your own classes, I would use parameters with default values ​​in the constructor, as this presentation shows. For instance:

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

And then you could just go through a dummy sleep function for testing or something else.

If you are trying to manipulate library classes through DI, (not what I really can imagine for use, but it looks like you're asking for), then I'm probably just a monkey to fix these classes to change all the necessary changes. For instance:

 import test_module def dummy_sleep(*args, **kwargs): pass test_module.time.sleep = dummy_sleep e = test_module.Example() e.foo() 
+6
source

Source: https://habr.com/ru/post/976371/


All Articles