类装饰器用于装饰类,用于管理类自身,或用于管理实例创建调用。
单体类,不管创建多少次实例,都只有一个实例的类。可以通过类装饰器管理装饰类的全部实例,实现单体类。
描述
通过类装饰器创建的类实例存放在全局字典,实现单体类。
(1) 定义全局字典instances;
(2) 类作为字典键,实例为字典值,不存在则创建,否则返回;
(3) 嵌套函数定义类装饰器,入参为类cls,返回可调用函数;
示例
>>> instances={}
>>> def getInstance(cls,*args):
if cls not in instances:
instances[cls]=cls(*args)
return instances[cls]
>>> def singlecls(cls):
def onCall(*args):
return getInstance(cls,*args)
return onCall
>>> @singlecls
class Clerk:
def __init__(self,name,rate,days):
self.name=name
self.rate=rate
self.days=days
def pay(self):
return self.rate*self.days
>>> @singlecls
class TestSingleCls:
def __init__(self,val):
self.attr=val
>>> C1=Clerk('梯阅线条',2000,22)
>>> c2=Clerk('tyxt',2100,23)
>>> C1.name,C1.pay()
('梯阅线条', 44000)
>>> c2.name,c2.pay()
('梯阅线条', 44000)
>>> tsc1=TestSingleCls(9555)
>>> tsc2=TestSingleCls(9556)
>>> tsc1.attr,tsc2.attr
(9555, 9555)
>>> id(C1),id(c2)
(11409136, 11409136)
>>> id(tsc1),id(tsc2)
(11410160, 11410160)
描述
通过嵌套函数的作用域来创建单体类。装饰的每个类使用各自的封闭作用域。
(1) 定义嵌套变量instance为None;
(2) 通过nonlocal为instance赋值,如果为None则创建实例,否则返回实例;
(3) 嵌套函数定义类装饰器,入参为类cls,返回可调用函数;
示例
>>> def singlecls(cls):
instance=None
def onCall(*args):
nonlocal instance
if instance is None:
instance=cls(*args)
return instance
return onCall
>>> @singlecls
class Clerk:
def __init__(self,name,rate,days):
self.name=name
self.rate=rate
self.days=days
def pay(self):
return self.rate*self.days
>>> C1=Clerk('梯阅线条',2000,22)
>>> C2=Clerk('tyxt',2100,23)
>>> id(C1)==id(C2),id(C1),id(C2)
(True, 11503152, 11503152)
>>> C1.name,C2.name
('梯阅线条', '梯阅线条')
描述
通过可调用类实例的装饰器实现单体类。
(1) 实例属性instance初始化为None;
(2) 如果instance为None则创建实例,否则返回实例;
(3) 定义可调用类实例,返回装饰类的实例;
示例
>>> class SingleCls:
def __init__(self,cls):
self.cls=cls
self.instance=None
def __call__(self,*args):
if self.instance is None:
self.instance=self.cls(*args)
return self.instance
>>> @SingleCls
class Clerk:
def __init__(self,name,rate,days):
self.name=name
self.rate=rate
self.days=days
def pay(self):
return self.rate*self.days
>>> C1=Clerk('梯阅线条',2000,22)
>>> C2=Clerk('tyxt',2100,23)
>>> id(C1)==id(C2),id(C1),id(C2)
(True, 11615440, 11615440)
>>> C1.name,C2.name
('梯阅线条', '梯阅线条')