如引言中所述,装饰器是可以应用于另一个功能以增强其行为的功能。语法糖等效于以下内容:。但是如果不是班级呢?该语法仍然有效,除了现在已被该类的实例替换。如果此类实现了magic方法,那么仍然可以像使用函数一样使用它:my_func = decorator(my_func)decoratormy_funcdecorator__call__()my_func
class Decorator(object): """简单的装饰器类。""" def __init__(self, func): self.func= func def __call__(self, *args, **kwargs): print('Before the function call.') res = self.func(*args, **kwargs) print('After the function call.') return res @Decorator def testfunc(): print('Inside the function.') testfunc() # 在函数调用之前。 # 在函数内部。 # 函数调用后。
请注意,从类型检查的角度来看,用类修饰器修饰的函数将不再被视为“函数”:
import types isinstance(testfunc, types.FunctionType) # 假 type(testfunc) # <class '__main__.Decorator'>
对于装饰方法,您需要定义其他__get__方法:
from types import MethodType class Decorator(object): def __init__(self, func): self.func= func def __call__(self, *args, **kwargs): print('Inside the decorator.') return self.func(*args, **kwargs) def __get__(self, instance, cls): # 如果在实例上调用了方法,则返回一个方法 return self if instance is None else MethodType(self, instance) class Test(object): @Decorator def __init__(self): pass a = Test()
在装饰器内。
类装饰器仅为特定功能生成一个实例,因此用类装饰器装饰方法将在该类的所有实例之间共享同一装饰器:
from types import MethodType class CountCallsDecorator(object): def __init__(self, func): self.func= func self.ncalls= 0 # 该方法的调用次数 def __call__(self, *args, **kwargs): self.ncalls+= 1 # 增加通话计数器 return self.func(*args, **kwargs) def __get__(self, instance, cls): return self if instance is None else MethodType(self, instance) class Test(object): def __init__(self): pass @CountCallsDecorator def do_something(self): return 'something was done' a = Test() a.do_something() a.do_something.ncalls # 1 b = Test() b.do_something() b.do_something.ncalls # 2