python之单例模式
在说单例模式前我们先看python在对类对象实例化及调用时都做了什么?
python在对类对象实例化及调用时用到了__init__和__new__方法。下面首先通过__init__和__new__方法的调用来了解这一过程。
一、__new__和__init__的区别
- __new__的作用:创建对象、分配内存
- __init__的作用:初始化对象
代码演示如下:
#__new__和__init__的区别
#先通过__new__创建对象,分配内存,然后使用__init__初始化对象 #所有的类都继承于object,__new__属于object中的方法。 # 调用我们平时定义的类时会自动的执行object类中的__new__方法创建对象,分配内存。 #下面将__new__ 方法重写后,可以看到从创建对象到初始化的全过程 class myclass(object): def __init__(self): #初始化对象 print('initialization') def __new__(cls, *args, **kwargs): print('Create object,assign memory') obj = super().__new__(cls) ##创建对象、分配内存 return obj def add(self,a ,b): return a + b if __name__ == '__main__': A = myclass()
print(A.add(2,3))
运行结果:
Create object,assign memory
initialization
5
以上结果可以看出,先执行__new__进行对象的创建和内存的分配,然后在用__init__进行初始化操作。
二、使用__new__实现单例模式
单例模式是什么?单例模式是指类有且仅有一个实例。
看下面的例子:
class myclass(object): def __init__(self): print('多实例') class singleton(object): """ 通过__new__方法实现单例模式 实现思路: 如果未创建对象,就创建对象并返回,如果已经创建对象则直接返回已创建的对象 """ obj = None def __new__(cls, *args, **kwargs): if cls.obj is None: cls.obj = super().__new__(cls) return cls.obj if __name__ == '__main__': print('------多实例------') A = myclass() B = myclass() print(id(A)) print(id(B)) print('------单实例------') C = singleton() D = singleton() print(id(C)) print(id(D))
返回结果:
------多实例------
多实例
多实例
2266588874176
2266587884008
------单实例------
2266591390184
2266591390184
通过上面的多实例和单实例的对比,能很清楚的明白单实例。
三、装饰器实现单例模式
通过装饰器实现单例模式,能方便的在大量需要单例模式的时候直接应用
""" 通过装饰器实现单例模式 """ def singleton(cls): obj = {} def wrapper(*args,**kwargs): if not obj : obj[cls] = cls(*args,**kwargs) ##obj字典中的键是类名,值为对象 return obj[cls] return wrapper @singleton class myclass(object): pass if __name__ == '__main__': A = myclass() print(id(A)) B = myclass() print(id(B))
结果如下:
1961581206664 1961581206664
四、类方法实现单例、多例共有模式
可以通过类方法实现一个类的单例创建对象和多例创建对象共存的模式,如下:
class mysgl(object): """ 类方法实现单例、双例共有模式 通过类方法创建的对象为单例模式 通过实例创建对象为多例模式 """ __instance = {} def __init__(self, *args, **kwargs): pass @classmethod def singleton(cls, *args, **kwargs): if not cls.__instance: cls.__instance[cls] = cls(*args,**kwargs) return cls.__instance[cls] if __name__ == '__main__': print('------类方法创建对象为单例对象------') A = mysgl.singleton() B = mysgl.singleton() print(id(A)) print(id(B)) print('------类实例创建对象为多例对象------') C = mysgl() D = mysgl() print(id(C)) print(id(D))
结果如下:
------类方法创建对象为单例对象------ 2725714123912 2725714123912 ------类实例创建对象为多例对象------ 2725714094400 2725745912296
五、创建线程安全的单例模式
略
当你试图去用自己的言语去讲清一些事物时,你会明白对此事物的理解是融会贯通还是一知半解