[英]Class as decorator for class method
我想使用装饰器做一些准备工作并记录函数具有的状态,所以我写了这样的东西:
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类的一个实例替换所有实例的方法。 它所做的就是:
Foo.test = Decorator(Foo.test)
这使得无法检测到调用的实例。 一种解决方法是用手将装饰器应用于Foo
的__init__
中:
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
的__call__
中传递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
的预期值。
我在这里
import functools
class Decorator(object):
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)
def __get__(self, instance, instancetype):
"""Implement the descriptor protocol to make decorating instance
method possible.
"""
# Return a partial function with the first argument is the instance
# of the class decorated.
return functools.partial(self.__call__, instance)
class Foo:
def __init__(self):
self.value = 0
@Decorator
def test(self, value):
self.value = value # change the value of instance
f = Foo()
f.test(3)
print(f.value) # prints 3
g = Foo()
g.test(8)
print(g.value) # prints 8
或可能是这个
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))
我发现使用Priyesh Kumar的答案,您可以将self参数从call方法简单地传递给要修饰的函数:
def __call__(self, *args, **kwargs):
return self.SafeGenerator(self.func(self, *args, **kwargs))
希望这可以帮助!
编辑:没关系,仅当通过装饰器传递的函数未调用init方法中定义的类变量时,才起作用
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.