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

2024/10/1 1:29:19

I'm coming from the C# world, so my views may be a little skewed. I'm looking to do DI in Python, however I'm noticing a trend with libraries where they all appear to rely on a service locator. That is, you must tie your object creation to the framework, such as injectlib.build(MyClass) in order to get an instance of MyClass.

Here is an example of what I mean -

from injector import Injector, injectclass 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 = innerinjector = 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 while automatically inferring dependency types based on parameter names? So if I have a constructor parameter called my_class, then an instance of MyClass will be injected. Reason I ask is that I don't see how I could inject a dependency into a class that gets created automatically via a third party library.

Answer

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

That said, neither "tying your object creation to the framework" nor the example code you gave seem terribly Pythonic, and this question in general is kind of confusing because DI in dynamic languages isn't really a big deal.

For general thoughts about DI in Python I'd say this presentation gives a pretty good overview of different approaches. For your specific question, I'll give two options based on what you might be trying to do.

If you're trying to add DI to your own classes, I would use paramaters with default values in the constructor, as that presentation shows. E.g:

import timeclass Example(object):def __init__(self, sleep_func=time.sleep):self.sleep_func = sleep_funcdef foo(self):self.sleep_func(10)print('Done!')

And then you could just pass in a dummy sleep function for testing or whatever.

If you're trying to manipulate a library's classes through DI, (not something I can really imagine a use case for, but seems like what you're asking) then I would probably just monkey patch those classes to change whatever needed changing. E.g:

import test_moduledef dummy_sleep(*args, **kwargs):passtest_module.time.sleep = dummy_sleep
e = test_module.Example()
e.foo()
https://en.xdnf.cn/q/71012.html

Related Q&A

Producing pdf report from python with bullet points

I would like to produce a dynamic pdf document from a python script that looks like the image below. Each sentence starts with a bullet point, and the text and number of lines depends on what the user …

Converting bits to bytes in Python

I am trying to convert a bit string into a byte string, in Python 3.x. In each byte, bits are filled from high order to low order. The last byte is filled with zeros if necessary. The bit string is ini…

Install python package from private pypiserver

I have setup a pypiserver behind an nginx proxy which uses htpasswd for authentication. I am currently able to upload sdists, but I cant figure out how to download them. I want to be able to download t…

Matplotlib Table- Assign different text alignments to different columns

I am creating a two column table and want the text to be as close as possible. How can I specify that the first column be right aligned and the second be left aligned?Ive tried by setting the general …

How would I make a random hexdigit code generator using .join and for loops?

I am new to programming and one assignment I have to do is create a random hexdigit colour code generator using for loops and .join. Is my program below even close to how you do it, or is it completely…

Multiline python regex

I have a file structured like this : A: some text B: more text even more text on several lines A: and we start again B: more text more multiline textIm trying to find the regex that will split my file …

How can I process xml asynchronously in python?

I have a large XML data file (>160M) to process, and it seems like SAX/expat/pulldom parsing is the way to go. Id like to have a thread that sifts through the nodes and pushes nodes to be processed …

python postgresql: reliably check for updates in a specific table

Situation: I have a live trading script which computes all sorts of stuff every x minutes in my main thread (Python). the order sending is performed through such thread. the reception and execution of …

How to push to remote repo with GitPython

I have to clone a set of projects from one repository and push it then to a remote repository automatically. Therefore im using python and the specific module GitPython. Until now i can clone the proje…

How do I do use non-integer string labels with SVM from scikit-learn? Python

Scikit-learn has fairly user-friendly python modules for machine learning.I am trying to train an SVM tagger for Natural Language Processing (NLP) where my labels and input data are words and annotatio…