python装饰器系列(七)
装饰器 利用__call__方法实现单例
所谓单例,是指一个类的实例从始至终只能被创建一次。单例的实现有多种,这里以__call__方法来实现
1 class Single: 2 __instance = None 3 4 def __init__(self,cls): 5 self.cls = cls 6 7 def __call__(self,*args,**kwargs): 8 if self.__instance is None: 9 self.__instance = self.cls(*args,**kwargs) 10 return self.__instance
1 @Single 2 class Grok1: 3 pass
1 grok1 = Grok1() 2 3 id(grok1) 4 140271956645592
1 grok2 = Grok1() 2 3 id(grok2) 4 140271956645592
1 id(grok1) == id(grok2) 2 True
分析一下上边的代码
1 @Single 2 class Grok1: 3 pass 4 grok1 = Grok1()
实例化Grok1类时相当于执行了下边两步:
1 1. Grok1 = Single(Grok1) 2 2. grok1 = Grok1()
第一步:执行Single(Grok1)是返回一个Single类的实例,并用一个变量Grok1指向这个实例对象,此时的Grok1不是class Grok1:里的Grok1类,只是名字相同而已,Single类实例化时__init__构建函数被调用,这里会把self.cls这个实例属性指向Grok1类。
第二步:因Single类实现了__call__方法,所以此实例是一个可调用对象,这里执行grok1 = Grok1(),其中的Grok1已不再是class Grok1:里的类,而是Single类的实例对象,这里调用实例对象就会执行__call__方法
对此方法中的代码做进一步分析:
1 def __call__(self,*args,**kwargs): 2 if self.__instance is None: 3 self.__instance = self.cls(*args,**kwargs) 4 return self.__instance
当第一次调用时,if语句的结果为True,此时会执行self.__instance = self.cls(*args,**kwargs),其中的self.cls指向Grok1类,即这里表示实例化Grok1类,并把self.__instance指向实例化Grok1类的对象,这样__instance就不再是None了,当第二次调用__call__函数时,if语句的结果为False,所以直接执行return self.__instance,所以Grok1这个对象在被多次实例化后指向的实例化对象都是一样的,其实是只被实例化了一次而已

浙公网安备 33010602011771号