functools.lru_cache() has two common uses. The first is as it was designed: an LRU cache for a function, with an optional bounded max size.
The other is as a replacement for this:
_obj = None def get_obj(): global _obj if _obj is None: _obj = create_some_object() return _obj
i.e lazy initialization of an object of some kind, with no parameters. You can find a few examples in the Django source code: https://github.com/django/django/search?q="%40lru_cache"&unscoped_q="%40lru_cache"
I’ve highlited some examples below:
There are lots of other examples in the ecosystem outside of Django - it’s a convenient way to lazy intialize objects like Boto3 clients, “default” instances or even ML models.
Looking at the source code in
_functoolsmodule.c I cannot see any special casing for these kind of functions. An
lru_cache on a function with no parameters is a bit of an oxymoron - there can only ever be one output and it cannot be dependent on any inputs.
I’d like to suggest that we add a special case to
lru_cache() for callables that have no parameters, to avoid the current overhead of using a
PyDict on every lookup and make it more akin the code sample above - a single PyObject variable that’s stored on the first call and returned on subsequent calls.
If there is a generally agreeable reception to this proposal, I’d really like to give this a shot as my first contribution to CPython.