Wie bringe ich functools.lru_cache dazu, neue Instanzen zurückzugeben?Python

Python-Programme
Anonymous
 Wie bringe ich functools.lru_cache dazu, neue Instanzen zurückzugeben?

Post by Anonymous »

Ich verwende Pythons lru_cache für eine Funktion, die ein veränderliches Objekt zurückgibt, etwa so:

Code: Select all

import functools

@functools.lru_cache()
def f():
x = [0, 1, 2]  # Stand-in for some long computation
return x
Wenn ich diese Funktion aufrufe, das Ergebnis mutiere und es erneut aufrufe, erhalte ich kein „frisches“, nicht mutiertes Objekt:

Code: Select all

a = f()
a.append(3)
b = f()
print(a)  # [0, 1, 2, 3]
print(b)  # [0, 1, 2, 3]
Ich verstehe, warum das passiert, aber es ist nicht das, was ich will. Eine Lösung wäre, dem Anrufer die Verantwortung für die Verwendung von list.copy:

zu überlassen

Code: Select all

a = f().copy()
a.append(3)
b = f().copy()
print(a)  # [0, 1, 2, 3]
print(b)  # [0, 1, 2]
Allerdings würde ich das gerne in f beheben. Eine hübsche Lösung wäre so etwas wie

Code: Select all

@functools.lru_cache(copy=True)
def f():
...
Obwohl von functools.lru_cache tatsächlich kein Kopierargument verwendet wird.

Irgendwelche Vorschläge, wie dieses Verhalten am besten implementiert werden kann?

Bearbeiten

Basierend auf der Antwort von Holdenweb ist dies meine endgültige Implementierung. Es verhält sich standardmäßig genau wie das integrierte functools.lru_cache und erweitert es um das Kopierverhalten, wenn copy=True angegeben wird.

Code: Select all

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]

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post