1

I have 3 modules: A, B, C

A contains a set of classes that B has fetchers for.

B contains a bunch of singletons that just deal with caching created objects and providing them when requested. Essentially just fetchers.

C is a list of functions that requires instances of A. 

The operation that I need to do is something along the lines of:

C::SomeFunc():
   B.getInstance("instance ID")


B::getInstance(someID: str) -> A:
   -look at cache, which is either [] or {}
   -if it is in cache, return that, else do:  A(someID)

My question is, how would you pass around the instances of these modules around? This question is primarily motivated by my lack of understanding of Python's memory allocation system.

I could do something along the lines of constructor-based dependency injection to get an instance of A,B,C where they need to go, and then have some "master/god/controller" object that just passes things where they need to go -

eg:

class god(object):
    def __init__(self):
        a = A()
        b = B()
        c = C(b)
.....
.....
class C(object):
    def __init__(self, B_instance):
         self.B = B_instance
    def SomeFunc(self, instanceID):
         self.B.getInstance(instanceID)

but this seems like a hack.

Any suggestions?

Thanks!

3 Answers 3

3

I've seen some packages that offer an instance provider on there on PyPI if that's what you are looking for. Personally, I didn't want to deal with another object to obtain instances. So I created my own library for this (Python 3 only). You only need @inject and annotations.

from py3njection import inject
from some_package import ClassToInject

class Demo:
    @inject
    def __init__(self, object_to_use: ClassToInject):
        self.dependency = object_to_use

demo = Demo()

You can find it here. It basically makes a new instance each time the method is called.

Testing is easy with this since you only have to pass mocks as arguments to unittest your function/method.

I've added @singleton too.

If you need even more instantiation ways, like the cache system you're describing, the docs explain how to easily implement your own. Everything cache related would be taken care of in a factory, and the objects that depends on them wouldn't have to know how to get them.

But if you're on Python 2 or if you need to have more control on injections, this could work too. But you still have to manipulate a provider.

Sign up to request clarification or add additional context in comments.

1 Comment

I am intrigued by how you're storing a reference to the singleton instance inside a classmethod. I've never seen a dependency injected through a static method. For the sake of ensuring finite lifetime and reducing global access, do you think it is possible to store the singleton in a container, rather than in a static method? For instance, would it be a trivial change storing it in a separate class that more traditionally manages the dependencies?
2

You can use injectable for that. It's a dependency injection autowiring micro-framework.

This is what your code would look like:

@injectable(singleton=True)
class MySingleton:
    ...
@autowired
def func_that_needs_my_singleton(my_singleton: Autowired(MySingleton)):
    ...

Comments

1

I recently released a small library that might help you achieve this. Feedback is very welcome :D

https://github.com/suned/serum

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.