由Python通过__new__实现单例模式,所想到的__new__和__init__方法的区别
Posted 潇湘旧友
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了由Python通过__new__实现单例模式,所想到的__new__和__init__方法的区别相关的知识,希望对你有一定的参考价值。
之前通过读书,了解到在Python中可以通过__new__方法来实现单例模式,代码一个示例如下,我就有了几个疑问,什么是单例模式?__new__方法是用来做什么的?用__new__方法实现的单例模式,比如下面的MyClass类,会对类的初始化有影响吗?会对类的实例方法、类方法、静态方法有影响吗?下面会说下我对这些概念的理解,如有错误,欢迎交流指出,在此表示感谢。
1 class SingleTon(object): 2 _instance = {} 3 4 def __new__(cls, *args, **kwargs): 5 if cls not in cls._instance: 6 cls._instance[cls] = super(SingleTon, cls).__new__(cls, *args, **kwargs) 7 print cls._instance 8 return cls._instance[cls] 9 10 11 class MyClass(SingleTon): 12 class_val = 22
首先说下单例模式,单例模式是确保一个类只有一个实例,并且这个实例是自己创造的,在系统中用到的都是这个实例。单例模式是设计模式的一种,关于设计模式和单例模式更具体的内容,可以查看相关的书本,在后面我也要好好学习一下这些东西。
下面主要说下__new__是用来干什么的,在Python中,__new__是用来创造一个类的实例的,而__init__是用来初始化这个实例的。既然__new__用来创造实例,也就需要最后返回相应类的实例,那么如果返回的是其他类的实例,结果如何呢?见下面的代码。以下代码运行后,首先打印出NoReturn __new__然后打印出other instance,最后通过type(t)可以看到t的类型是<class ‘__main__.Other‘>,可以知道如果__new__中不返回本类的实例的话,是没法调用__init__方法的。想要返回本类的实例,只需要把以下代码中12行的Other()改成super(NoReturn, cls).__new__(cls, *args, **kwargs)即可。
1 class Other(object): 2 val = 123 3 4 def __init__(self): 5 print ‘other instance‘ 6 7 8 class NoReturn(object): 9 10 def __new__(cls, *args, **kwargs): 11 print ‘NoReturn __new__‘ 12 return Other() 13 14 def __init__(self, a): 15 print a 16 print ‘NoReturn __init__‘ 17 18 t = NoReturn(12) 19 print type(t)
最后来说用__new__方法实现的单例模式,会对实例方法,类方法,静态方法,实例变量和类变量有影响吗?答案是对相应的方法是没有影响的,但是如果用不同的变量都初始化了这个实例,在后面的变量中修改实例变量和类变量的话,前面的也会相应修改,而这也正好符合单例,无论多少个变量指向了这个实例,他们指向的是同一个。在__new__中产生完实例后,每次初始化实例对象,都是产生的同一个实例,而这个实例中相关的方法、变量还是和普通的实例一样使用。测试代码以及输出如下:
1 class MyClass(SingleTon): 2 class_val = 22 3 4 def __init__(self, val): 5 self.val = val 6 7 def obj_fun(self): 8 print self.val, ‘obj_fun‘ 9 10 @staticmethod 11 def static_fun(): 12 print ‘staticmethod‘ 13 14 @classmethod 15 def class_fun(cls): 16 print cls.class_val, ‘classmethod‘ 17 18 19 if __name__ == ‘__main__‘: 20 a = MyClass(1) 21 b = MyClass(2) 22 print a is b # True 23 print id(a), id(b) # 4367665424 4367665424 24 # 类型验证 25 print type(a) # <class ‘__main__.MyClass‘> 26 print type(b) # <class ‘__main__.MyClass‘> 27 # 实例方法 28 a.obj_fun() # 2 obj_fun 29 b.obj_fun() # 2 obj_fun 30 # 类方法 31 MyClass.class_fun() # 22 classmethod 32 a.class_fun() # 22 classmethod 33 b.class_fun() # 22 classmethod 34 # 静态方法 35 MyClass.static_fun() # staticmethod 36 a.static_fun() # staticmethod 37 b.static_fun() # staticmethod 38 # 类变量 39 a.class_val = 33 40 print MyClass.class_val # 22 41 print a.class_val # 33 42 print b.class_val # 33 43 # 实例变量 44 print b.val # 2 45 print a.val # 2
以上是关于由Python通过__new__实现单例模式,所想到的__new__和__init__方法的区别的主要内容,如果未能解决你的问题,请参考以下文章