单例模式指确保某个类在整个系统中只存在一个实例的一种设计模式
使用单例模式的好处:
1、每个实例都会占用一定的内存资源,且初始化实例时会影响运行性能,所以当整个系统只需一个实例时,使用单例模式不仅可减少资源占用,而且因为只初始化一次,还可以加快运行性能。例如当程序通过一个类来读取配置信息,而程序多个地方需要使用配置信息,这时整个程序运行过程中只需一个实例对象即可,可减少占用内存资源,同时还可以保证程序在多处地方获取的配置信息一致。
2、使用单例模式可进行同步控制,计数器同步、程序多处读取配置信息这些情景下若只存在一个实例,即可保证一致性。
在python中,一般可使用一下4种方式实现单例模式:
1、通过模块调用
2、使用__new__方法
3、使用装饰器
4、使用元类(metaclass)
一、通过模块调用
做法:将需要实现单例的类写在模块文件中,然后通过import引入该模块,即可得到单例对象。
原理:在python3中,首次导入模块文件时,会在程序目录下的__pycache__目录中生成pyc文件,之后再导入时,将直接加载pyc文件。从而实现单例。
实现代码:
module_demo.py
class singleton_cal:
def foo(self):
pass
export_singleton = singleton_cal()
use_module.py
from module_demo import export_singleton
a = export_singleton
from module_demo import export_singleton
b = export_singleton
print(a == b)
print(id(a) ==>
可发现,多次调用/导入模块,使用的都是同一个实例对象
二、使用__new__方法
_new__与_init__的区别:
__new\:创建实例对象时调用的构造方法
_init_ :初始化方法,用于设置实例的相关属性
python创建实例时,会先调用__new__构造方法,然后使用__init__进行实例初始化。
我们可以通过__new__来影响实例的创建,从而实现单例。
实现代码:
class Singleton(object): __instance = None
def __new__(cls,*args,**kwargs):
if not cls. __instance:
cls.__instance = super().__new__(cls,*args,**kwargs)
return cls.__instance
a = Singleton()
b = Singleton()
print(a == b)
print(id(a) ==>
上面代码中,声明了一个私有类变量__instance,当__instance不为None时,代表系统中已有实例,直接返回该实例,若__instance为None时,表示系统中还没有该类实例,则创建新实例并返回。
三、使用装饰器
from functools import wraps
def singleton(cls):
instances = {}
@wraps(cls)
def getinstance(*args, **kwargs):
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return getinstance
@singleton
class singleCls(object):
def foo(self):
pass
a = singleCls()
b = singleCls()
print(a == b)
print(id(a) ==>
只有当第一次调用singleCls时,装饰器才会从instances={}开始执行,之后调用singleCls时,都只执行getinstance函数,这是装饰器的特性,利用这个特性,当我们多次调用singleCls时,在getinstance函数中判断该类是否存在于instances字典中,若不存在,则创建该类实例并加入instances字典中,并返回字典中该类的实例;若存在,则直接返回字典中该类的实例。可利用该装饰器为多个类实现单例。
四、使用元类(metaclass)
元类创建了所有的类型对象(包括object对象),系统默认的元类是type。
实例,类,父类,元类的关系可表示为下图
元类中的__call方法,在已该类为元类的类创建实例时调用,例如:类A以类B为元类,当A创建实例时,B中的\ call将会被调用。利用\ call__可实现对实例创建的控制。
实现代码:
class SingletonMeta(type): __instance = None
def __call__(cls,*args,**kwargs):
if not cls.__instance:
cls.__instance = type.__call__(cls,*args,**kwargs)
return cls.__instance
class myclass(metaclass = SingletonMeta):
def foo(self):
pass
a = myclass()
b = myclass()
print(a==b)
print(id(a)==id(b))
自定义元类时,通常继承自type,声明一个私有类变量__instance保存类实例,当__instance为None时,调用type的__call__方法为类创建实例,保存到__instance并返回;若__instance不为None,则直接返回__instance,不重新创建实例。
欢迎扫码关注公众号“KeepCode”,分享更多技术好文,并提供技术电子书籍免费下载,每天进步一点点~~~~
运维网声明
1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网 享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com