Python单例模式

Python单实例

#1 环境

Python3.8.1

#2 什么是单实例

单例模式就是确保一个类只有一个实例.当你希望整个系统中,某个类只有一个实例时,单例模式就派上了用场

#3 实现单实例方式

#3.1 非单实例

class MyClass(object):

    def foo(self):

        return None

obj1 = MyClass()
obj2 = MyClass()
print(obj1 is obj2)
print(id(obj1))
print(id(obj2))

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sQaWZCJg-1582358419143)(https://raw.githubusercontent.com/Coxhuang/yosoro/master/20200221131107-image.png)]

#3.2 使用模块

class MyClass(object):

    def foo(self):

        return None

obj = MyClass()

使用:

from singleton.mysingleton import obj

python的模块就是天然的单例模式,因为模块在第一次导入的时候,会生成.pyc文件,当第二次导入的时候,就会直接加载.pyc文件,而不是再次执行模块代码.如果我们把相关的函数和数据定义在一个模块中,就可以获得一个单例对象了

#3.3 使用装饰器


def singleton(cls):
    """装饰器函数"""

    class_instance = {} # 定义一个接受实例的类 

    def singleton_inner(*args, **kwargs):

        if cls not in class_instance: # 判断该类是否被实例化过 
            class_instance[cls] = cls(*args, **kwargs) # 没有被实例化过 -> 实例化 -> 将实例化的对象添加到字典中  

        return class_instance[cls] # 返回实例化对象 

    return singleton_inner 

@singleton
class MyClass(object):

    def foo(self):

        return None

obj1 = MyClass()
obj2 = MyClass()
print(obj1 is obj2)
print(id(obj1))
print(id(obj2))

20200221145958-image.png

在类前加个装饰器,在这里装饰器的目的只有一个,就是在类实例化前,先判断这个类有没有实例化过,如果没有,则实例化,如果实例化过,测返回之前的实例化对象

#3.4 使用类

class MyClass(object):

    def foo(self):

        return None

    @classmethod
    def get_instance(cls, *args, **kwargs):
        """实例化函数"""

        if not hasattr(cls, '_instance'):
            cls._instance = cls(*args, **kwargs)

        return cls._instance


obj1 = MyClass.get_instance()
obj2 = MyClass.get_instance()
print(obj1 is obj2)
print(id(obj1))
print(id(obj2))
obj3 = MyClass()
print(id(obj3))

20200222145424-image.png

以这种方式实现单实例,有两个弊端:

  1. 只有MyClass.get_instance()这样子实例化对象才能实现单实例,如果是使用MyClass()这种方式实例化,则不能实现单实例
  2. 多线程的时候,很可能会出现多个实例,因为当调用这个类方法的时候get_instance(),如果在实例化过程中__init__函数消耗很长时间,那么其他的线程的实例化,就会认为自己是第一个实例化,这样以来,就会导致出现多个实例

#3.5 重写__new__方法(推荐)

class MyClass(object):

    def foo(self):

        return None

    def __new__(cls, *args, **kwargs):
        if not hasattr(cls, '_instance'):
            cls._instance = super().__new__(cls)

        return cls._instance


obj1 = MyClass()
obj2 = MyClass()
print(obj1 is obj2)
print(id(obj1))
print(id(obj2))

20200222155934-image.png

一个对象的实例化过程是先执行类的__new__方法,如果我们没有写,默认会调用object的__new__方法,返回一个实例化对象,然后再调用__init__方法,对这个对象进行初始化,我们可以根据这个实现单例

发布了113 篇原创文章 · 获赞 36 · 访问量 5万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章