单例模式

单例概念:

单例是一个特殊的类,这个类只能创建一个实例

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)) 

 

posted @ 2020-06-04 20:18  乔乔新  阅读(143)  评论(0编辑  收藏  举报