我使用的是Python 3.10。考虑这个缓存的玩具示例,它缓存对实例方法的第一次调用,然后在后续调用中返回缓存的值:
import functools
def cache(func):
@functools.wraps(func) # for __name__
def wrapper(*args, **kwargs):
if not wrapper.cache:
print("caching...")
wrapper.cache = func(*args, **kwargs)
return wrapper.cache
wrapper.cache = None
return wrapper
class Power:
def __init__(self, exponent):
self.exponent = exponent
@cache
def of(self, base):
return base ** self.exponent
# test
>>> cube = Power(3)
>>> cube.of(2)
caching...
8
>>> cube.of.cache
8
>>> cube.of.__dict__
{'__wrapped__': <function __main__.Power.of(self, base)>, 'cache': 8}
>>> cube.of.cache = None
...
AttributeError: 'method' object has no attribute 'cache'
我有两个问题:
1.)接受的答案here说,
@cache
装饰器在构造Power
类时运行,并且将传递一个unbound方法(在我的例子中是of
)。我想只有当您使用类装饰器装饰实例方法时,这种说法才是正确的。存在一个问题,您需要将 cube
对象的引用存储在装饰类实例构造中,但 cube
实例尚未定义。我很难将这种说法与我的示例有效的事实相协调;装饰的 of
方法传递一个元组,第一个元素是 cube
实例,第二个元素是 base=2
参数
2.) 我可以访问
.cache
属性,但为什么无法重置它?它给出了AttributeError
。
发生的情况是,装饰机制将
cache(of)
的结果分配给 Power.of
。所以 Power
具有属性 of
(你的缓存装饰器)。
您可以写:
Power.of.cache = None
来获得您想要的:
cube = Power(3)
print(cube.of(2))
print(cube.of(2))
Power.of.cache = None
print(cube.of(2))
输出:
caching...
8
8
caching...
8