Since the function has no parameters and is pre-computed, why force all
users to *call* it? The @once decorator could just return the value of
calling the function:

def once(func):
    return func()

@once
def pwd():
    return os.getcwd()

print(pwd)

On Sun, Apr 26, 2020 at 7:09 AM Tom Forbes <t...@tomforb.es> wrote:

> Hello,
> 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. My
> rationale for suggesting this addition is twofold:
>
> First: It’s fairly common to use `lru_cache()` to implement this
> behaviour. We use this inside Django (example
> <https://github.com/django/django/blob/77aa74cb70dd85497dbade6bc0f394aa41e88c94/django/forms/renderers.py#L19>),
> internally in other projects at my workplace, inside the stdlib itself
> <https://github.com/python/cpython/blob/2fa67df605e4b0803e7e3aac0b85d851b4b4e09a/Lib/ipaddress.py#L1324>
>  and
> in numerous other projects. In the first few pages of a Github code search
> <https://github.com/search?l=Python&q=%22functools.lru_cache%22&type=Code> it
> is fairly easy to find examples, any decorated method with no parameters is
> using `lru_cache()` like `once()`. 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.
>
> Second: Implementing this in Python, in my opinion, crosses the line of
> “annoying and non-trivial enough to not want to repeatedly do it”. While a
> naive (untested) implementation might be:
>
> def 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
>
> While to the people who are likely going to be reading this mailing this
> the code above is understandable and potentially even somewhat simple.
> However to a lot of people who might not have had experience with writing
> decorators or understand sentinel objects and their use the above code
> might be incomprehensible. A much more common, and in my opinion worse,
> implementation that I’ve seen is something along the lines of this:
>
> _value = None
> def get_value():
>     nonlocal _value
>     if _value is None:
>         _value = some_function()
>     return _value
>
> Which is not ideal for obvious reasons. And these are not even including a
> potentially key feature: locking the wrapped function so that it is only
> called once if it is invoked from multiple threads at once.
>
> So, I’d like to propose adding a `once()` decorator to functools that:
> 1. Has a C implementation, keeping the speed on-par with `lru_cache()`
> 2. Ensures that the wrapped function is only called once when invoked by
> multiple threads
>
> For some related discussion about this idea and lru_cache, please see my
> thread on
> <https://discuss.python.org/t/reduce-the-overhead-of-functools-lru-cache-for-functions-with-no-parameters/3956>
> discuss.python.org.
> _______________________________________________
> Python-ideas mailing list -- python-ideas@python.org
> To unsubscribe send an email to python-ideas-le...@python.org
> https://mail.python.org/mailman3/lists/python-ideas.python.org/
> Message archived at
> https://mail.python.org/archives/list/python-ideas@python.org/message/5OR3LJO7LOL6SC4OOGKFIVNNH4KADBPG/
> Code of Conduct: http://python.org/psf/codeofconduct/
>


-- 
--Guido van Rossum (python.org/~guido)
*Pronouns: he/him **(why is my pronoun here?)*
<http://feministing.com/2015/02/03/how-using-they-as-a-singular-pronoun-can-change-the-world/>
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/MNZS6XLDUHASJJOHQ3OQZVYWRLTNJJ2W/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to