类装饰器
类装饰器主要依赖于函数__call__()
,每当调用一个类的实例时,函数__call__()
就会被执行一次。
from functools import wraps
class Decorator:
def __init__(self, func):
wraps(func)(self) #类装饰器中使用wraps得作为函数调用
self.func = func
def __call__(self, *args, **kwargs): #__call__方法:使类像函数一样被调用
print("这是一个类装饰器")
f = self.func(*args, **kwargs)
return f
@Decorator
def output(x):
return x
print(output(6))
输出:
这是一个类装饰器
6
但是如果在类中的方法上使用这个装饰器的话会报错。
class Spam:
@Decorator
def output(self, x):
return x
s = Spam()
print(s.output(x=5))
TypeError: output() missing 1 required positional argument: 'self'
为了让装饰器可以同时工作在类定义的内部和外部,类装饰器中还要添加一个方法__get__()
,参考描述器协议了解更多。
from functools import wraps
import types
class Decorator:
def __init__(self, func):
wraps(func)(self) #类装饰器中使用wraps得作为函数调用
self.func = func
def __call__(self, *args, **kwargs):
print("这是一个类装饰器")
f = self.func(*args, **kwargs)
return f
def __get__(self, instance, owner): #创建一个绑定方法对象 (最终会给这个方法传递self参数)
if instance is None:
return self # 如果这个方法是在类上面来访问, 那么 __get__()中的instance参数会被设置成None并直接返回Decorator实例本身
else:
return types.MethodType(self, instance) #type.MethodType() 手动创建一个绑定方法来使用
这样上面的例子就可以正常执行。输出:
这是一个类装饰器
5