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:
---
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, <[email protected]> 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:
> 1. Developers are using "lru_cache" to achieve this right now, which is less
> efficient than it could be
> 2. 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
> 3. Implementing a thread-safe (or even non-thread safe) "call_once" method is
> non-trivial
> 4. It complements the lru_cache and cached_property methods currently present
> in functools.
>
> The specifics of the method would be:
> 1. The wrapped method is guaranteed to only be called once when called for
> the first time by concurrent threads
> 2. Only functions with no arguments can be wrapped, otherwise an exception is
> thrown
> 3. 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.
>
> 1.
> https://mail.python.org/archives/list/[email protected]/thread/5OR3LJO7LOL6SC4OOGKFIVNNH4KADBPG/#5OR3LJO7LOL6SC4OOGKFIVNNH4KADBPG
> 2.
> https://discuss.python.org/t/reduce-the-overhead-of-functools-lru-cache-for-functions-with-no-parameters/3956
> _______________________________________________
> Python-Dev mailing list -- [email protected]
> To unsubscribe send an email to [email protected]
> https://mail.python.org/mailman3/lists/python-dev.python.org/
> Message archived at
> https://mail.python.org/archives/list/[email protected]/message/5CFUCM4W3Z36U3GZ6Q3XBLDEVZLNFS63/
> Code of Conduct: http://python.org/psf/codeofconduct/
--
Night gathers, and now my watch begins. It shall not end until my death.
_______________________________________________
Python-Dev mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at
https://mail.python.org/archives/list/[email protected]/message/2I6YNJIRSQD4VCQHPVX5WDHTBQJPTCPH/
Code of Conduct: http://python.org/psf/codeofconduct/