Victor Stinner wrote:
Hi, A pattern that I used multiple times is to compute an object attribute only once and cache the result into the object. Dummy example:
How is that different from https://docs.python.org/3/library/functools.html?highlight=cached_property#f... -Brett
class X: def __init__(self, name): self.name = name self._cached_upper = None def _get(self): if self._cached_upper is None: print("compute once") self._cached_upper = self.name.upper() return self._cached_upper upper = property(_get)
obj = X("victor") print(obj.upper) print(obj.upper) # use cached value It would be interesting to be able to replace obj.upper property with an attribute (to reduce the performance overhead of calling _get() method), but "obj.upper = value" raises an error since the property prevents to set the attribute. I understood that the proposed @called_once would store the cached value into the function namespace. Victor Le lun. 27 avr. 2020 à 23:44, tom@tomforb.es a écrit :
Hello, After a great discussion in python-ideas[1][2] it was suggested that I cross-post this proposal to python-dev to gather more comments from those who don't follow python-ideas. The proposal is to add a "call_once" decorator to the functools module that, as the name suggests, calls a wrapped function once, caching the result and returning it with subsequent invocations. The rationale behind this proposal is that:
Developers are using "lru_cache" to achieve this right now, which is less efficient than it could be Special casing "lru_cache" to account for zero arity methods isn't trivial and we shouldn't endorse lru_cache as a way of achieving "call_once" semantics Implementing a thread-safe (or even non-thread safe) "call_once" method is non-trivial It complements the lru_cache and cached_property methods currently present in functools.
The specifics of the method would be:
The wrapped method is guaranteed to only be called once when called for the first time by concurrent threads Only functions with no arguments can be wrapped, otherwise an exception is thrown There is a C implementation to keep speed parity with lru_cache
I've included a naive implementation below (that doesn't meet any of the specifics listed above) to illustrate the general idea of the proposal: def call_once(func): sentinel = object() # in case the wrapped method returns None obj = sentinel @functools.wraps(func) def inner(): nonlocal obj, sentinel if obj is sentinel: obj = func() return obj return inner
I'd welcome any feedback on this proposal, and if the response is favourable I'd love to attempt to implement it.
https://mail.python.org/archives/list/python-ideas@python.org/thread/5OR3LJO... https://discuss.python.org/t/reduce-the-overhead-of-functools-lru-cache-for-...
Python-Dev mailing list -- python-dev@python.org To unsubscribe send an email to python-dev-leave@python.org https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/5CFUCM4W... Code of Conduct: http://python.org/psf/codeofconduct/ --
Night gathers, and now my watch begins. It shall not end until my death.