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))
复制
#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))
复制

在类前加个装饰器,在这里装饰器的目的只有一个,就是在类实例化前,先判断这个类有没有实例化过,如果没有,则实例化,如果实例化过,测返回之前的实例化对象
#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))
复制
以这种方式实现单实例,有两个弊端:
- 只有MyClass.get_instance()这样子实例化对象才能实现单实例,如果是使用MyClass()这种方式实例化,则不能实现单实例
- 多线程的时候,很可能会出现多个实例,因为当调用这个类方法的时候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))
复制
一个对象的实例化过程是先执行类的__new__方法,如果我们没有写,默认会调用object的__new__方法,返回一个实例化对象,然后再调用__init__方法,对这个对象进行初始化,我们可以根据这个实现单例