类装饰器是管理类的一种方式,不是包装单个函数或方法,而是用装饰器的额外逻辑,来包装实例的构建和调用,从而实现对主体类的扩展。
主体类被装饰后,通过主体类创建实例对象时,自动调用装饰器返回的包装器函数,而包装器函数内部会自动调用原来的主体类。
用法
def cls_decorator(cls):
pass
return aCallable
描述
cls_decorator:装饰器函数;
cls:类入参
aCallable:可调用对象
类装饰器函数接收一个类,并且返回可调用对象,赋值给原类名。
用法
@cls_decorator
class AClass:
pass
ac=AClass(8)
等价于
class AClass:
pass
AClass=cls_decorator(AClass)
ac=AClass(8)
描述
@cls_decoratro:@类装饰器函数,下一行接class 主体类;
class AClass:定义主体类;
类装饰器用来装饰类。
执行过程:
@cls_decoraotr:python文件被加载时,@cls_decorator自动调用cls_decorator(AClass)装饰器函数,并且将下一行class定义的类对象AClass作为入参,装饰器返回可调用对象,赋值给类变量AClass。
aCallable:可调用对象,可以是原类,或者新类。
AClass:被重新赋值为可调用对象。
AClass(8):相当于调用可调用对象aCallable(8),而aCallable会将相关操作,给到入参接收到的原类AClass进行操作。
最终,装饰器实现了对主体类的扩展,而且不修改主体类的代码逻辑,不改变主体类的调用方式,即可执行装饰器扩展的额外逻辑。
示例
>>> def cls_decorator(cls):
print('cls=',cls)
print('clsid=',id(cls))
print('cls_decorator 被调用返回原类')
return cls
>>> @cls_decorator
class TestClsDeco:
print('TestClsDeco 被调用')
# TestClsDeco 先被执行
TestClsDeco 被调用
# cls_decorator 后被执行
cls= <class '__main__.TestClsDeco'>
clsid= 2624479393088
cls_decorator 被调用返回原类
>>> id(TestClsDeco)
# id 相同, cls 送给 cls_decorator的入参
2624479393088
描述
先执行主体类,再调用类装饰器,并且将主体类传给装饰器。
用法
def cls_decorator(cls):
# 添加修改原类cls的行为
return cls # 返回原类cls
描述
类装饰器函数接收一个原类cls,装饰器内部添加修改原类的行为,并且返回原类,从而实现对原类的定制-装饰。
示例
>>> def cls_decorator(cls):
print('cls_decorator 被调用返回原类')
print('原类添加属性 name')
cls.name='梯阅线条'
return cls
>>> @cls_decorator
class TestClsDeco:
print('TestClsDeco 被调用')
def __init__(self,url):
self.url=url
TestClsDeco 被调用
cls_decorator 被调用返回原类
原类添加属性 name
>>> tcd=TestClsDeco('tyxt.work')
>>> tcd.name
'梯阅线条'
>>> tcd.url
'tyxt.work'
用法
def cls_decorator(cls):
class CLS_Wrapper:
def __init__(self,*args):
self.wrapped=cls(*args)
# 拦截未定义属性的点号运算
def __getattr__(self,attr):
# 指向原类属性的点号运算
return getattr(self.wrapped,attr)
return CLS_Wrapper
描述
返回的类包装器是一个新类,与原类不同,并且将新类赋值给原类名称。
self.wrapped=cls:将原类赋值给类包装器的实例属性。
__getattr__():拦截类包装器的实例属性的点号运算。getattr可以使用属性管理的其他内置函数,比如__getattribute__(),__setattr__(),__delattr__(),__call__(),__str__()等,对属性进行管理和拦截。
return getattr(self.wrapped,attr):将拦截的点号运算,指向原类示例属性的点号运算。
return CLS_Wrapper:返回新类。
示例
>>> def cls_decorator(cls):
print('clsid=',id(cls))
class CLS_Wrapper:
def __init__(self,*args):
self.wrapped=cls(*args)
def __getattr__(self,attr):
return getattr(self.wrapped,attr)
print('CLS_Wrapperid=',id(CLS_Wrapper))
return CLS_Wrapper
>>> @cls_decorator
class AClass:
def __init__(self,name):
self.name=name
clsid= 2624479396864
CLS_Wrapperid= 2624479365712
# AClass 赋值为新类 CLS_Wrapper , id 相同
>>> id(AClass)
2624479365712
>>> ac=AClass('梯阅线条')
>>> ac.name
'梯阅线条'