单例模式
单例概念:
单例是一个特殊的类,这个类只能创建一个实例
eg:windows 系统的回收站,点击一次打开后,再去点击还是展示的之前打开的窗口,不会打开新的窗口
单例作用:
节省内存空间。因为产生不同的对象,会产生不同的内存地址,造成资源的浪费。
应用场景:日志logger插入,计时器、权限校验、网站计数器,windows资源管理器,回收站,线程池,数据库连接池等资源池。
1、通过__new__实现单例模式
class singleton(): __isinstance = None def __new__(cls, *args, **kwargs): if cls.__isinstance is None: #判断之前是否有实例,没有就创建,有就不走这个分支,直接返回之前的 cls.__isinstance = object.__new__(cls) #object.__new__(cls)是创建一个实例 return cls.__isinstance #返回实例 a = singleton() print(id(a)) #2331573055272 b = singleton() print(id(b)) #2331573055272
class singleton(): __isinstance = None def __init__(self,name): self.name = name def __new__(cls, *args, **kwargs): if cls.__isinstance is None: cls.__isinstance = object.__new__(cls) return cls.__isinstance #返回实例 a = singleton("张三") print(id(a)) #2331573055272 b = singleton("李四") print(id(b)) #2331573055272 print(a.name) #李四 因为a,b其实是同一个实例,所有b改变了name值,a的name值也跟着改变
2、通过装饰器实现
def singletion(cls): instances = {} def getinstance(*args,**kwargs): if cls not in instances: instances[cls] = cls(*args,**kwargs) return instances[cls] return getinstance @singletion class Singletion(): def __init__(self,name): self.name = name print(f"__init__方法执行<---{self.name}") s = Singletion("s") print("对象s已创建。。。")#该实例调用了__init__方法 s1 = Singletion("s1") print("对象s1已创建。。。")#该实例没调用__init__方法 print(s is s1)
3、通过导入模块时实现
python的模块就是天然的单例模式,因为模块在第一次导入的时候,会生成.pyc文件,当第二次导入的时候,就会直接加载.pyc文件,而不是再次执行模块代码。
将Foo类在某个文件(test1.py)中实例化,赋值给某个变量v。在其他文件如test2.py中引入该实例,多次引用打印其内存地址,发现是一样。
#test1.py class Foo(object): def test(self): print("123") v = Foo() #实例化
#test2.py from test1 import v as v1 print(v1, id(v1)) from test1 import v as v2 print(v2,id(v2))