To może działać - dodanie atrybutu class jeżeli nie istnieje używając metaklasa:
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
zacząłem myśleć i zorientował się, że atrybut klasy może być również Singleton która dziedziczy z dict.
temp.py i test.py - jak wyżej
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))
Następnie:
>>> 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
>>>
Co jest 'B' w * Wszystkie instancje B powinny dzielić jeden "cache" *? –
przestrzenie nazw są różne. –
Mój zły (odnosząc się do usuniętej odpowiedzi). Sądzę, że nie miałoby to sensu, jeśli nie mielibyśmy pracy, gdybyśmy drukowali różne rzeczy. – Dair