>  t...@tomforb.es wrote:
> 
> I would like to suggest adding a simple “once” method to functools. As the 
> name suggests, this would be a decorator that would call the decorated 
> function, cache the result and return it with subsequent calls.

It seems like you would get just about everything you want with one line:

    call_once = lru_cache(maxsize=None)

which would be used like this:

   @call_once
   def welcome():
       len('hello')

> Using lru_cache like this works but it’s not as efficient as it could be - in 
> every case you’re adding lru_cache overhead despite not requiring it.


You're likely imagining more overhead than there actually is.  Used as shown 
above, the lru_cache() is astonishingly small and efficient.  Access time is 
slightly cheaper than writing d[()]  where d={(): some_constant}. The 
infinite_lru_cache_wrapper() just makes a single dict lookup and returns the 
value.¹ The lru_cache_make_key() function just increments the empty args tuple 
and returns it.²   And because it is a C object, calling it will be faster than 
for a Python function that just returns a constant, "lambda: some_constant()".  
This is very, very fast.


Raymond


¹ https://github.com/python/cpython/blob/master/Modules/_functoolsmodule.c#L870
² https://github.com/python/cpython/blob/master/Modules/_functoolsmodule.c#L809






> 
> 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/python-id...@python.org/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 -- python-dev@python.org
> To unsubscribe send an email to python-dev-le...@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/5CFUCM4W3Z36U3GZ6Q3XBLDEVZLNFS63/
> Code of Conduct: http://python.org/psf/codeofconduct/
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@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/OYBYJ2373OTHALHTPQJV5EBX6N5M4DDL/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to