用装饰函数装饰类的实例方法

问题描述 投票:0回答:1

我使用的是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

python python-decorators
1个回答
0
投票

发生的情况是,装饰机制将

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
© www.soinside.com 2019 - 2024. All rights reserved.