1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
|
from threading import RLock
_missing = object()
class (object): """A decorator that converts a function into a lazy property. The function wrapped is called the first time to retrieve the result and then that calculated result is used the next time you access the value. Works like the one in Werkzeug but has a lock for thread safety. """
def __init__(self, func, name=None, doc=None): self.__name__ = name or func.__name__ self.__module__ = func.__module__ self.__doc__ = doc or func.__doc__ self.func = func self.lock = RLock()
def __get__(self, obj, type=None): if obj is None: return self with self.lock: value = obj.__dict__.get(self.__name__, _missing) if value is _missing: value = self.func(obj) obj.__dict__[self.__name__] = value return value In [27]: class B: ...: @locked_cached_property ...: def foo(self): ...: import time ...: ...: print('processing....') ...: time.sleep(10) ...: return 'b' ...: ...:
In [28]: b = B()
In [29]: b.foo processing.... Out[29]: 'b'
In [30]: b.foo Out[30]: 'b'
In [31]:
|
近期评论