Python 类作为类方法的装饰器
我想使用一个装饰器来做一些准备工作,并记录函数的状态,所以我写了如下内容:Python 类作为类方法的装饰器,python,decorator,Python,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.f
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
对应于Decorator
的实例,而不是Foo
的实例,这将使f.value
保持不变,但f.test.value
增加
有没有办法将Foo
的实例传递给Decorator
而不是Decorator
本身
或者有没有更清晰地实现这一功能的方法
感谢高级版。因为decorator只被调用一次,并且用decorator类的一个实例替换了所有实例的方法。它所做的只是:
这使得无法检测调用的实例。一种解决方法是手动在Foo
的\uuuu init\uuuu
中应用装饰器:
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)
这样,装饰器包装实例方法,因此您不需要在装饰器的调用中传递self
:
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)
它按预期输出两次1
。我得到了这个
或
可能是这个
def preJob(function):
def updateToDo(self, *args, **kwargs):
# do some recording
function(self, *args, **kwargs)
return updateToDo
class Foo(object):
def __init__(self):
self.value = 0
@preJob
def test(self, value):
self.value = value
f = Foo()
f.test(3)
print(f.value) # prints 3
g = Foo()
g.test(8)
print(g.value) # prints 8
我发现,使用Priyesh Kumar的答案,您可以简单地将自变量从调用方法传递到被修饰的函数:
def __call__(self, *args, **kwargs):
return self.SafeGenerator(self.func(self, *args, **kwargs))
希望这有帮助
编辑:
仅当通过decorator传递的函数不调用init方法中定义的类变量时,“别管”才起作用f.test.value做什么?我200%确定我没有完全理解您的问题。正如在代码中一样,您希望记录调用@Decorator方法的次数。那很好,但你以后怎么才能查到那笔钱。我试过一个例子,在这个例子中,您可以将Foo的实例传递给Decorator,但f.test.value不起作用。您可以使用f.test.count
访问计数,其中f
是Foo
的实例。
def preJob(function):
def updateToDo(self, *args, **kwargs):
# do some recording
function(self, *args, **kwargs)
return updateToDo
class Foo(object):
def __init__(self):
self.value = 0
@preJob
def test(self, value):
self.value = value
f = Foo()
f.test(3)
print(f.value) # prints 3
g = Foo()
g.test(8)
print(g.value) # prints 8
class threadSafeGenerator(object):
"""docstring for threadSafeGenerator"""
class SafeGenerator(object):
"""docstring for SafeGenerator"""
def __init__(self, iterable):
self.iterable = iterable
self.lock = Lock()
def __iter__(self):
return self
def __next__(self):
with self.lock:
return next(self.iterable)
def __init__(self, func):
super(threadSafeGenerator, self).__init__()
self.func = func
def __call__(self, *args, **kwargs):
return self.SafeGenerator(self.func(self, *args, **kwargs))
def __call__(self, *args, **kwargs):
return self.SafeGenerator(self.func(self, *args, **kwargs))