This may work - add a class attribute if it does not already exist using the metaclass:
foo.py:
def load_stuff(): return {'foo':1, 'bar':2} class F(type): def __new__(meta, name, bases, namespace): if 'cache' not in namespace: print('adding cache') namespace['cache'] = load_stuff() return super().__new__(meta, name, bases, namespace) class MyCache(metaclass = F): def __init__(self): print(len(MyCache.cache))
test.py:
print(__name__) import foo print(foo.MyCache.cache) print('********************')
tmp.py:
print('tmp.py') import foo print('*******************') import test
>>> import tmp tmp.py adding cache ******************* test {'foo': 1, 'bar': 2} ******************** >>> tmp.foo.MyCache.cache {'foo': 1, 'bar': 2} >>> tmp.test.foo.MyCache.cache {'foo': 1, 'bar': 2} >>> tmp.test.foo.MyCache.cache['x'] = 'x' >>> tmp.test.foo.MyCache.cache {'foo': 1, 'bar': 2, 'x': 'x'} >>> tmp.foo.MyCache.cache {'foo': 1, 'bar': 2, 'x': 'x'} >>> >>> tmp.foo.MyCache.cache is tmp.test.foo.MyCache.cache True >>>
>>> import test test adding cache {'foo': 1, 'bar': 2} ******************** >>> test.foo.MyCache.cache {'foo': 1, 'bar': 2} >>> >>> import tmp tmp.py ******************* >>> >>> tmp.foo.MyCache.cache {'foo': 1, 'bar': 2} >>> >>> tmp.foo.MyCache.cache['x'] = 'x' >>> tmp.foo.MyCache.cache {'foo': 1, 'bar': 2, 'x': 'x'} >>> test.foo.MyCache.cache {'foo': 1, 'bar': 2, 'x': 'x'} >>> >>> z = tmp.foo.MyCache() 3 >>> z.cache {'foo': 1, 'bar': 2, 'x': 'x'} >>> >>> z.cache['y'] = 'y' >>> z.cache {'foo': 1, 'bar': 2, 'x': 'x', 'y': 'y'} >>> test.foo.MyCache.cache {'foo': 1, 'bar': 2, 'x': 'x', 'y': 'y'} >>> tmp.foo.MyCache.cache {'foo': 1, 'bar': 2, 'x': 'x', 'y': 'y'} >>> >>> tmp.foo.MyCache.cache is test.foo.MyCache.cache True
I started thinking and realized that a class attribute can also be a single that inherits from dict.
temp.py and test.py are the same as above
foo.py:
def load_stuff(): return [('a', 1), ('b', 2)] class Borg: _shared_state = {} def __new__(cls, *a, **k): obj = super().__new__(cls, *a, **k) obj.__dict__ = cls._shared_state return obj class Cache(dict, Borg): pass class OneCache(metaclass = F): cache = Cache(load_stuff()) def __init__(self): print(len(OneCache.cache))
Then:
>>> import tmp >>> tmp.foo.OneCache.cache {'a': 1, 'b': 2} >>> tmp.test.foo.OneCache.cache {'a': 1, 'b': 2} >>> z = tmp.foo.OneCache() 2 >>> z.cache['r'] = 't' >>> z.cache {'a': 1, 'b': 2, 'r': 't'} >>> tmp.foo.OneCache.cache {'a': 1, 'b': 2, 'r': 't'} >>> tmp.test.foo.OneCache.cache {'a': 1, 'b': 2, 'r': 't'} >>> >>> tmp.foo.OneCache.cache is tmp.test.foo.OneCache.cache is z.cache True >>>