我想用一个decorator来做一些准备工作并记录函数的状态,所以我写了这样的东西:

class Decorator:
    def __init__(self, func):
        self.count = 0
        self.func = func

    def __call__(self, *args, **kwargs):
        self.count += 1 # Simply count the call times
        return self.func(self, *args, **kwargs)

class Foo:
    def __init__(self):
        self.value = 0

    @Decorator
    def test(self, value):
        self.value = value # change the value of instance
        print(self.value)

f = Foo()
f.test(1)

print(f.value)
print(f.test.value)

但很明显,self中的__call__(self, *args, **kwargs)对应于Decorator的实例,而不是Foo的实例,这将使f.value保持不变,但f.test.value增加。
有什么方法可以将Foo的实例传递给Decorator而不是Decorator本身吗?
或者有什么方法可以更清楚地实现这个功能?
提前谢谢。

最佳答案

因为decorator只调用一次,并用decorator类的一个实例替换所有实例的方法。它所做的就是:

Foo.test = Decorator(Foo.test)

这使得无法检测调用的实例。一种解决方法是手动应用__init__Foo中的decorator:
class Foo:
    def __init__(self):
        self.value = 0
        self.test = Decorator(self.test)

    def test(self, value):
        self.value = value # change the value of instance
        print(self.value)

这样,decorator包装实例方法,因此您不需要在self__call__中传递Decorator
class Decorator:
    def __init__(self, func):
        self.count = 0
        self.func = func

    def __call__(self, *args, **kwargs):
        self.count += 1 # Simply count the call times
        return self.func(*args, **kwargs)

现在它工作了,你必须更新你的测试方法,因为f.test.value不再存在:
f = Foo()
f.test(1)

print(f.value)

它输出两倍于预期的a1

关于python - 类作为类方法的装饰器,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/37792257/

10-16 22:13