Можно ли использовать lru_cache для создания синглтона?

Есть такой код:

@lru_cache()
def get_service(
    redis: Redis = Depends(get_redis),
    es: AsyncElasticsearch = Depends(get_elastic)
) -> Service:
    return Service(es=es, redis=redis)

Можно ли такую реализацию использовать для создания синглтона? Учитывая, что Redis и ES экземпляры не меняются (то есть всегда одинаковые).


Ответы (1 шт):

Автор решения: Fox Fox
Использование @lru_cache() оправдано, если:
— функция зависит только от аргументов, не выполняет побочных действий;
— в циклах вызывается с одинаковыми аргументами;
— вычисления ресурсоёмкие: рекурсия и т.д.;
— количество уникальных входов ограничено.
Не стоит использовать, если:
— функция зависит от внешних факторов: времени, сети, БД;
— аргументы всегда уникальны;
— есть побочные действия: запись в файл, логирование, вывод и т.д.

Вот простой пример целесообразности использования кэша:

# Вычисление чисел последовательности Фибоначчи
from functools import lru_cache
import time

# Без кеша
def fib_no_cache(n):
 if n < 2: return n
 return fib_no_cache(n-1) + fib_no_cache(n-2)

# С кешем
@lru_cache(maxsize=None)
def fib_cache(n):
 if n < 2: return n
 return fib_cache(n-1) + fib_cache(n-2)

# Тест производительности
v_start = time.time()
v_result_no_cache = fib_no_cache(40)
print(f"fib_no_cache(40) = {v_result_no_cache}")
print("Время вычисления без кеша:", time.time() - v_start, "сек.")

v_start = time.time()
v_result_cache = fib_cache(40)
print(f"fib_cache(40) = {v_result_cache}")
print("Время вычисления с кешем:", time.time() - v_start, "сек.")

input("Нажмите Enter для продолжения...")

Вот результат:

fib_no_cache(40) = 102334155
Время вычисления без кеша: 15.758745670318604 сек.
fib_cache(40) = 102334155
Время вычисления с кешем: 0.000141143798828125 сек.
→ Ссылка