装饰器 利用__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
这个对象在被多次实例化后指向的实例化对象都是一样的,其实是只被实例化了一次而已