
Why not? It's a decorator, isn't it? Just make it check for number of arguments at decoration time and return a different object.
It’s not that it’s impossible, but I didn’t think the current implementation doesn’t make it easy (https://github.com/python/cpython/blob/cecf049673da6a24435acd1a6a3b34472b323... <https://github.com/python/cpython/blob/cecf049673da6a24435acd1a6a3b34472b323...>). You’d ideally want to skip creating all these objects and special case `user_function` having no parameters, but then you have an issue with `cache_info()` being passed `cache_len()`. So maybe it’s simplest to use the `cache` dictionary with a single static key, but then you’re not really helping much, or avoiding this method altogether, which seemed pretty messy. The C implementation seemed easier to implement - you could re-use the `cache` member (https://github.com/python/cpython/blob/cecf049673da6a24435acd1a6a3b34472b323... <https://github.com/python/cpython/blob/cecf049673da6a24435acd1a6a3b34472b323...>) and store the result of the function call, but that also seemed sub-optimal as the `root` member doesn’t make much sense to be there. At least, that was my line of thought. It basically seemed that it would be more trouble than it was potentially worth, and it might be better to spend my time on `call_once` than special-casing `lru_cache`.
But presumably we should be making lru_cache thread safe if it isn’t.
lru_cache is indeed thread-safe but it doesn’t guarantee that the wrapped method is only called _once_ per unique set of arguments. It apparently just ensures that the internal state of the cache is not corrupted by concurrent accesses.
It's unfortunate that cached_property doesn't work at module level
It is indeed, but a solution that works generally in any function defined at the module level or not would be good to have.
On 27 Apr 2020, at 22:55, Steve Dower <steve.dower@python.org> wrote:
On 27Apr2020 2237, tom@tomforb.es wrote:
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
Why not? It's a decorator, isn't it? Just make it check for number of arguments at decoration time and return a different object.
That way, people can decorate their functions now and get correct behaviour (I assume?) on 3.8 and earlier, and also a performance improvement on 3.9, without having to do any version checking.
This part could even be written in Python.
3. Implementing a thread-safe (or even non-thread safe) "call_once" method is non-trivial
Agree that this is certainly true. But presumably we should be making lru_cache thread safe if it isn't.
4. It complements the lru_cache and cached_property methods currently present in functools.
It's unfortunate that cached_property doesn't work at module level (as was pointed out on the other threads - thanks for linking those, BTW).
Cheers, Steve