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

 
 

 

posted @ 2019-05-25 12:39  旧梦一场  阅读(191)  评论(0编辑  收藏  举报