I would like to have a Python @cache
decorator based on identity, not __hash__
/__equal
.
That is to say, I would like the cached value for an argument ka
NOT to be used for a different object ka2
, even if ka == ka2
.
Is there a way to do that?
In code:
from functools import cache
class Key:
def __init__(self, value):
self.value = value
def __eq__(self, another):
print(f"__eq__ {self.value}, {another.value}")
return another.value == self.value
def __hash__(self):
print(f"__hash__ {self.value}")
return hash(self.value)
def __repr__(self):
return self.value
i = 0
@cache
def foo(key):
global i
i += 1
print(f"Computing foo({key}) = {i}")
return i
ka = Key('a')
ka2 = Key('a')
print(f"foo(ka): {foo(ka)}")
print(f"foo(ka2): {foo(ka2)}") # I would like the cached value for ka NOT to be used even though ka2 == ka.
Make a wrapper like Key
that compares by the identity of its wrapped object, and wrap your caching function in a helper that uses the wrapper:
class Id:
__slots__="x",
def __init__(self,x): self.x=x
def __hash__(self): return id(self.x)
def __eq__(self,o): return self.x is o.x
def cache_id(f):
@functools.cache
def id_f(i): return f(i.x)
@functools.wraps(f)
def call(x): return id_f(Id(x))
return call
@cache_id
def foo(key): …