Python中的单例模式,python实现单例模式
本文分享了五种用Python创建singleton模式的常用方法,供大家参考。具体情况如下
所谓singleton,就是一个类的实例从头到尾只能创建一次。
方法1:
如果希望一个类从头到尾最多有一个实例,那么使用__new__方法会非常简单。Python中的类通过__new__创建实例:
一个
2
三
四
五
六
七
八
九
10
11
12
13
类单例(对象):
def __new__(cls,*args,**kwargs):
如果不是hasattr(cls, _inst ):
cls。_inst=super(Singleton,cls)。__new__(cls,*args,**kwargs)
返回cls。_inst
if __name__==__main__ :
A类(单例):
def __init__(self,s):
self.s=s
a=A(苹果)
b=A(“香蕉”)
打印id(a),a.s
打印id(b),b.s
结果:
29922256香蕉
29922256香蕉
通过__new__方法,类的实例在创建时被绑定到类property _inst。如果cls。_inst为None,这意味着该类尚未实例化。实例化该实例并将其绑定到cls。_inst,然后每次都返回第一次实例化创建的实例。从Singleton派生子类时,注意不要重载__new__。
方法二:
有时候,我们并不关心生成的实例是否有相同的id,而只关心它们的状态和行为。我们可以允许创建许多实例,但所有实例都共享状态和行为:
一个
2
三
四
五
六
博格类(对象):
_shared_state={}
def __new__(cls,*args,**kwargs):
obj=super(博格,cls)。__new__(cls,*args,**kwargs)
obj。__dict__=cls。_共享状态
返回对象
将所有实例的__dict__指向同一个字典,以便实例共享相同的方法和属性。任何实例的name属性的设置,无论是在__init__中修改还是直接修改,都会影响所有实例。但是,实例的id是不同的。要确保类实例可以共享属性,但不能共享子类,请注意使用cls。_shared_state而不是Borg。_共享状态。
因为实例是不同的id,所以每个实例都可以是字典的键:
一个
2
三
四
五
六
七
八
九
10
11
12
13
if __name__==__main__ :
类别示例(博格):
及格
a=示例()
b=示例()
c=示例()
adict={}
j=0
对于iin a、b、c:
adict[i]=j
j=1
对于iin a、b、c:
打印指南[i]
结果:
0
一个
2
如果这种行为不是您想要的,您可以在Borg类中添加__eq__和__hash__方法,使其更接近单例模式的行为:
一个
2
三
四
五
六
七
八
九
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
博格类(对象):
_shared_state={}
def __new__(cls,*args,**kwargs):
obj=super(博格,cls)。__new__(cls,*args,**kwargs)
obj。__dict__=cls。_共享状态
返回对象
def __hash__(self):
返回1
def __eq__(自己,其他):
尝试:
回归自我。_ _ dict _ _是其他。__词典_ _
除了:
返回False
if __name__==__main__ :
类别示例(博格):
及格
a=示例()
b=示例()
c=示例()
adict={}
j=0
对于iin a、b、c:
adict[i]=j
j=1
对于iin a、b、c:
打印指南[i]
结果:
2
2
2
的所有实例都可以用作键。
方法3
帅哥写类的时候,某种机制会用类名,基类元组,类字典来创建类对象。在新的类中,这个机制默认为type,并且这个机制是可编程的,叫做metaclass __metaclass__。
一个
2
三
四
五
六
七
八
九
10
11
12
13
14
类Singleton(类型):
def __init__(self,name,bases,class_dict):
超级(单身,自己)。__init__(name,bases,class_dict)
自我。_ instance=无
def __call__(self,*args,**kwargs):
如果自我。_ instanceis无:
自我。_instance=super(Singleton,self)。__call__(*args,**kwargs)
回归自我。_实例
if __name__==__main__ :
A类(对象):
__元类_ _=单例
a=A()
b=A()
打印id(a),id(b)
结果:
34248016 34248016
Id是一样的。
在示例中,我们构造了一个单例元类,并使用__call__方法使其模拟函数的行为。当构造类A时,它的元类被设置为Singleton,因此当创建类A时,行为如下:
A=Singleton (name,bases,class _ dict),A实际上是Singleton类的一个实例。
创建A的实例时,A ()=singleton (name,bases,class _ dict) ()=singleton (name,bases,class _ dict)。_ _ call _ _(),从而将A的所有实例指向A的attribute _instance,这个方法其实和方法1是一样的。
方法4
python中的module模块在程序中只加载一次,本身就是一个singleton。你可以直接写一个模块,把你需要的方法和属性作为函数和模块作用域的全局变量写在模块里,根本不用写类。
有一些方法可以集成模块和类的优点:
一个
2
三
四
五
六
七
八
九
10
11
12
13
class _singleton(对象):
类ConstError(TypeError):
及格
def __setattr__(self,name,value):
如果自我命名。__词典_ _:
提升自我。常数误差
自我。__字典_ _[名称]=值
def __delattr__(self,name):
如果自我命名。__词典_ _:
提升自我。常数误差
引发名称错误
导入系统
sys . modules[_ _ name _ _]=_ singleton()
Python不会检查sys.modules以确保它们是模块对象。我们用这个把模块绑定到一个类对象上,以后都绑定到同一个对象上。
将代码存储在single.py中:
一个
2
三
导入单个
single.a=1
single.a=2
常数误差
德尔单身
常数误差
方法五:
最简单的方法:
一个
2
三
类单例(对象):
及格
singleton=singleton()
将名称singleton绑定到实例,singleton是自己类的唯一对象。
以上是Python singleton模式实现的详细介绍,希望对大家的学习有所帮助。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。