What if the functions requires arguments? How to cache calls withThen I think lru_cache is perfectly suitable for that use case. `once()` would only be useful if you’re calling a function with no arguments and therefore return a constant value. I originally thought that an exception could be raised if `@once()` was used with a function that accepted arguments, but it might be better to instead simply ignore arguments instead? It could help with some situations where your method accepts a single “self” argument, or another value, that you know will be constant across calls.
different arguments? What if some arguments are not hashable?
Why ``functools``? Why not your own library or a package at PyPI. LikeBecause `lru_cache` fits the use case almost perfectly, is available in the stdlib and is very, very fast. As such people are using it like they would use `once()` which to me feels like a good argument to either special case `lru_cache()` to account for this or explicitly add a complimentary `once()` method alongside `lru_cache`. Adding a complimentary method seems better.
https://pypi.org/project/cachetools/ ?
On Sun, Apr 26, 2020 at 03:03:16PM +0100, Tom Forbes <tom@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()
What if the functions requires arguments? How to cache calls with
different arguments? What if some arguments are not hashable?
Why ``functools``? Why not your own library or a package at PyPI. Like
https://pypi.org/project/cachetools/ ?
> 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 <http://discuss.python.org/>.
Oleg.
--
Oleg Broytman https://phdru.name/ phd@phdru.name
Programmers don't die, they just GOSUB without RETURN.
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-leave@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/74ZGZRB4JF6EPVB5E7WHL44KZUGEUELV/
Code of Conduct: http://python.org/psf/codeofconduct/