Mail.ruПочтаМой МирОдноклассникиВКонтактеИгрыЗнакомстваНовостиКалендарьОблакоЗаметкиВсе проекты

Вопрос по пайтон

Poul Lirman Ученик (152), на голосовании 1 месяц назад
как написать функцию, которая принимает любую функцию f и возвращает её оптимизированную версию f_opt, которая кэширует результаты вызовов f для любых возможных аргументов, включая изменяемые объекты, такие как списки, словари и даже другие функции? При этом нужно обеспечить, чтобы кэширование работало корректно даже при изменении аргументов после вызова, и избежать утечек памяти. Как это реализовать без использования сторонних библиотек?
Голосование за лучший ответ
Дмитрий Дмитриев Просветленный (40323) 2 месяца назад
Чтобы создать функцию, которая кэширует результаты вызовов другой функции в Python, включая изменяемые объекты, можно использовать следующий подход. Мы будем использовать словарь для хранения кэшированных результатов и уникальные ключи для каждого набора аргументов. Для изменяемых объектов мы будем сериализовать их содержимое, чтобы избежать проблем с изменениями после вызова функции.
Вот пример реализации:
python
import json
import hashlib

def cache_key(*args, **kwargs):
"""Создает уникальный ключ для кэширования на основе аргументов функции."""
# Сериализуем аргументы и создаем хеш
key = json.dumps((args, kwargs), sort_keys=True)
return hashlib.md5(key.encode()).hexdigest()

def memoize(func):
"""Декоратор для кэширования результатов функции."""
cache = {}

def wrapper(*args, **kwargs):
# Генерируем ключ для кэша
key = cache_key(*args, **kwargs)

# Проверяем, есть ли результат в кэше
if key in cache:
return cache[key]

# Вызываем оригинальную функцию и кэшируем результат
result = func(*args, **kwargs)
cache[key] = result

return result

return wrapper

# Пример использования
@memoize
def expensive_function(x, y):
# Имитация дорогой вычислительной операции
return x ** 2 + y ** 2

# Вызовы функции
print(expensive_function(3, 4)) # Вычислит и кэширует результат
print(expensive_function(3, 4)) # Использует кэшированный результат
print(expensive_function(4, 5)) # Вычислит и кэширует новый результат

Объяснение кода:
cache_key: Эта функция создает уникальный ключ на основе аргументов функции. Мы используем json.dumps для сериализации аргументов и hashlib.md5 для создания хеша.
memoize: Это декоратор, который оборачивает вашу функцию. Он создает словарь cache, где будут храниться результаты вызовов функции.
wrapper: Внутренняя функция, которая проверяет наличие результата в кэше и вызывает оригинальную функцию, если результата нет.
Примечания:
Этот подход работает для неизменяемых типов данных (чисел, строк и кортежей) и сериализуемых изменяемых объектов (списки и словари). Однако он не будет работать с объектами, которые нельзя сериализовать (например, открытые файлы или сокеты).
Убедитесь, что вы контролируете размер кэша, чтобы избежать утечек памяти. Вы можете добавить логику для удаления старых записей из кэша при достижении определенного размера.
Рустам Абдрашитов Мыслитель (9542) 2 месяца назад
 def cache_function(f): 
cache = {}

def f_opt(*args):
key = tuple(map(repr, args))
if key not in cache:
cache[key] = f(*args)
return cache[key]

return f_opt

@cache_function
def expensive_function(x):
return x * x
Poul LirmanУченик (152) 2 месяца назад
го*но не рабочее, ты вообще условие понял?
Похожие вопросы