Как заставить functools.lru_cache возвращать новые экземпляры?Python

Программы на Python
Ответить
Anonymous
 Как заставить functools.lru_cache возвращать новые экземпляры?

Сообщение Anonymous »

Я использую lru_cache Python для функции, которая возвращает изменяемый объект, например:

import functools

@functools.lru_cache()
def f():
x = [0, 1, 2] # Stand-in for some long computation
return x


Если я вызову эту функцию, изменю результат и вызову ее снова, я не получу «свежий», неизмененный объект:

a = f()
a.append(3)
b = f()
print(a) # [0, 1, 2, 3]
print(b) # [0, 1, 2, 3]


Я понимаю, почему это происходит, но это не то, чего я хочу. Решением было бы оставить вызывающему абоненту ответственность за использование list.copy:

a = f().copy()
a.append(3)
b = f().copy()
print(a) # [0, 1, 2, 3]
print(b) # [0, 1, 2]


Однако я хотел бы исправить это внутри f. Симпатичным решением было бы что-то вроде

@functools.lru_cache(copy=True)
def f():
...


хотя аргумент copy на самом деле не принимается functools.lru_cache.

Есть предложения относительно того, как лучше всего реализовать это поведение?

Изменить

Основываясь на ответе Holdenweb, это моя окончательная реализация. По умолчанию он ведет себя точно так же, как встроенный functools.lru_cache, и расширяет его поведением копирования, если указан copy=True.

import functools
from copy import deepcopy

def lru_cache(maxsize=128, typed=False, copy=False):
if not copy:
return functools.lru_cache(maxsize, typed)
def decorator(f):
cached_func = functools.lru_cache(maxsize, typed)(f)
@functools.wraps(f)
def wrapper(*args, **kwargs):
return deepcopy(cached_func(*args, **kwargs))
return wrapper
return decorator

# Tests below

@lru_cache()
def f():
x = [0, 1, 2] # Stand-in for some long computation
return x

a = f()
a.append(3)
b = f()
print(a) # [0, 1, 2, 3]
print(b) # [0, 1, 2, 3]

@lru_cache(copy=True)
def f():
x = [0, 1, 2] # Stand-in for some long computation
return x

a = f()
a.append(3)
b = f()
print(a) # [0, 1, 2, 3]
print(b) # [0, 1, 2]


Подробнее здесь: https://stackoverflow.com/questions/549 ... -instances
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Python»