I want to pass a variable(iterable )between instances of different classes. I have a structure similar with the one below.
Each class has its own module(so no globals) and needs to work in python 3 and 2.
class O:
pass
class A(O):
pass
class B(O):
def __init__(self, cache):
self.cache = cache
class B1(B):
def p(self):
self.cache.add_to_cache("32", "something something")
class B2(B):
def p(self):
self.cache.get_from_cache("52", "something else")
For B
and its sub-classes I want to create a cache. All instances of this classes(B, B1, B2) to use the same cache.
To keep it simple, let's say that the cache is just a dict.
c = {}
a = A(c)
b1 = B() - needs c
b1.p()
b2 = C() - needs c
b2.p()
print(cache)
Off course the example above, is wrong because the cache is different for each instance.
The chache should be :
{
"32", "something something"
"52": "something else"
}
Another approach to this is using CacheService as an injectable Singleton service, which I consider a better practice.
Read this first for a code/syntax solution to your direct question, or continue reading for a solution with better design.
class O(object):
pass
class CacheService(object):
__instances = {}
@staticmethod
def getinstance(owner_id):
if owner_id not in CacheService.__instances:
CacheService.__instances[owner_id] = CacheService(owner_id)
return CacheService.__instances[owner_id]
def __init__(self, owner_id):
self._owner_id = owner_id
self._owner_query = CacheService.__name__ + self._owner_id
self._cache = {}
def put_in_cache(self, key, value):
self._cache[self._owner_query + str(key)] = value
def get_from_cache(self, key):
return self._cache.get(self._owner_query + str(key), "the_default")
class B(O):
def __init__(self):
self._cache = CacheService.getinstance(B.__name__)
class B1(B):
def __init__(self):
super(B1, self).__init__()
def p(self):
val1 = self._cache.get_from_cache("a")
print(val1)
class B2(B):
def __init__(self):
super(B2, self).__init__()
def p(self):
self._cache.put_in_cache("a", 2)
if __name__ == "__main__":
b1 = B1()
b2 = B2()
b2.p()
b1.p()
out:
2
This still uses a class variable, but hides it from your "everyday code", and moves it to the "infrastructure level".
I see this as cleaner, as now your class hierarchy shouldn't handle its own global variables.