亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

5種Python單例模式的實(shí)現(xiàn)方式

系統(tǒng) 1971 0

本文為大家分享了Python創(chuàng)建單例模式的5種常用方法,供大家參考,具體內(nèi)容如下

所謂單例,是指一個(gè)類(lèi)的實(shí)例從始至終只能被創(chuàng)建一次。
方法1:
如果想使得某個(gè)類(lèi)從始至終最多只有一個(gè)實(shí)例,使用__new__方法會(huì)很簡(jiǎn)單。Python中類(lèi)是通過(guò)__new__來(lái)創(chuàng)建實(shí)例的:

            
class Singleton(object):
  def __new__(cls,*args,**kwargs):
    if not hasattr(cls,'_inst'):
      cls._inst=super(Singleton,cls).__new__(cls,*args,**kwargs)
    return cls._inst
if __name__=='__main__':
  class A(Singleton):
    def __init__(self,s):
      self.s=s   
  a=A('apple')  
  b=A('banana')
  print id(a),a.s
  print id(b),b.s

          

結(jié)果:
29922256 banana
29922256 banana
通過(guò)__new__方法,將類(lèi)的實(shí)例在創(chuàng)建的時(shí)候綁定到類(lèi)屬性_inst上。如果cls._inst為None,說(shuō)明類(lèi)還未實(shí)例化,實(shí)例化并將實(shí)例綁定到cls._inst,以后每次實(shí)例化的時(shí)候都返回第一次實(shí)例化創(chuàng)建的實(shí)例。注意從Singleton派生子類(lèi)的時(shí)候,不要重載__new__。
方法2:
有時(shí)候我們并不關(guān)心生成的實(shí)例是否具有同一id,而只關(guān)心其狀態(tài)和行為方式。我們可以允許許多個(gè)實(shí)例被創(chuàng)建,但所有的實(shí)例都共享狀態(tài)和行為方式:

            
class Borg(object):
  _shared_state={}
  def __new__(cls,*args,**kwargs):
    obj=super(Borg,cls).__new__(cls,*args,**kwargs)
    obj.__dict__=cls._shared_state
    return obj

          

將所有實(shí)例的__dict__指向同一個(gè)字典,這樣實(shí)例就共享相同的方法和屬性。對(duì)任何實(shí)例的名字屬性的設(shè)置,無(wú)論是在__init__中修改還是直接修改,所有的實(shí)例都會(huì)受到影響。不過(guò)實(shí)例的id是不同的。要保證類(lèi)實(shí)例能共享屬性,但不和子類(lèi)共享,注意使用cls._shared_state,而不是Borg._shared_state。
因?yàn)閷?shí)例是不同的id,所以每個(gè)實(shí)例都可以做字典的key:

            
if __name__=='__main__':
  class Example(Borg):
    pass
  a=Example()
  b=Example()
  c=Example()
  adict={}
  j=0
  for i in a,b,c:
    adict[i]=j
    j+=1
  for i in a,b,c:
    print adict[i]

          

結(jié)果:
0
1
2
如果這種行為不是你想要的,可以為Borg類(lèi)添加__eq__和__hash__方法,使其更接近于單例模式的行為:

            
class Borg(object):
  _shared_state={}
  def __new__(cls,*args,**kwargs):
    obj=super(Borg,cls).__new__(cls,*args,**kwargs)
    obj.__dict__=cls._shared_state
    return obj
  def __hash__(self):
    return 1
  def __eq__(self,other):
    try:
      return self.__dict__ is other.__dict__
    except:
      return False
if __name__=='__main__':
  class Example(Borg):
    pass
  a=Example()
  b=Example()
  c=Example()
  adict={}
  j=0
  for i in a,b,c:
    adict[i]=j
    j+=1
  for i in a,b,c:
    print adict[i]

          

結(jié)果:
2
2
2
所有的實(shí)例都能當(dāng)一個(gè)key使用了。
方法3
當(dāng)你編寫(xiě)一個(gè)類(lèi)的時(shí)候,某種機(jī)制會(huì)使用類(lèi)名字,基類(lèi)元組,類(lèi)字典來(lái)創(chuàng)建一個(gè)類(lèi)對(duì)象。新型類(lèi)中這種機(jī)制默認(rèn)為type,而且這種機(jī)制是可編程的,稱(chēng)為元類(lèi)__metaclass__ 。

            
class Singleton(type):
  def __init__(self,name,bases,class_dict):
    super(Singleton,self).__init__(name,bases,class_dict)
    self._instance=None
  def __call__(self,*args,**kwargs):
    if self._instance is None:
      self._instance=super(Singleton,self).__call__(*args,**kwargs)
    return self._instance
if __name__=='__main__':
  class A(object):
    __metaclass__=Singleton    
  a=A()
  b=A()
  print id(a),id(b)

          

結(jié)果:
34248016 34248016
id是相同的。
例子中我們構(gòu)造了一個(gè)Singleton元類(lèi),并使用__call__方法使其能夠模擬函數(shù)的行為。構(gòu)造類(lèi)A時(shí),將其元類(lèi)設(shè)為Singleton,那么創(chuàng)建類(lèi)對(duì)象A時(shí),行為發(fā)生如下:
A=Singleton(name,bases,class_dict),A其實(shí)為Singleton類(lèi)的一個(gè)實(shí)例。
創(chuàng)建A的實(shí)例時(shí),A()=Singleton(name,bases,class_dict)()=Singleton(name,bases,class_dict).__call__(),這樣就將A的所有實(shí)例都指向了A的屬性_instance上,這種方法與方法1其實(shí)是相同的。
?方法4
python中的模塊module在程序中只被加載一次,本身就是單例的。可以直接寫(xiě)一個(gè)模塊,將你需要的方法和屬性,寫(xiě)在模塊中當(dāng)做函數(shù)和模塊作用域的全局變量即可,根本不需要寫(xiě)類(lèi)。
而且還有一些綜合模塊和類(lèi)的優(yōu)點(diǎn)的方法:

            
class _singleton(object):
  class ConstError(TypeError):
    pass
  def __setattr__(self,name,value):
    if name in self.__dict__:
      raise self.ConstError
    self.__dict__[name]=value
  def __delattr__(self,name):
    if name in self.__dict__:
      raise self.ConstError
    raise NameError
import sys
sys.modules[__name__]=_singleton()

          

python并不會(huì)對(duì)sys.modules進(jìn)行檢查以確保他們是模塊對(duì)象,我們利用這一點(diǎn)將模塊綁定向一個(gè)類(lèi)對(duì)象,而且以后都會(huì)綁定向同一個(gè)對(duì)象了。
將代碼存放在single.py中:

            
>>> import single
>>> single.a=1
>>> single.a=2

          

ConstError
>>> del single.a
ConstError
方法5:
最簡(jiǎn)單的方法:

            
class singleton(object):
  pass
singleton=singleton()

          

將名字singleton綁定到實(shí)例上,singleton就是它自己類(lèi)的唯一對(duì)象了。

以上就是Python單例模式的實(shí)現(xiàn)方式詳細(xì)介紹,希望對(duì)大家的學(xué)習(xí)有所幫助。


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 日韩精品一区二三区中文 | 大乳孕妇一级毛片 | 欧美亚洲综合另类型色妞 | 五月天婷婷在线视频 | 欧美日韩一区二区三 | 国产国语一级a毛片高清视频 | 久热热热| 亚洲高清在线播放 | 思思久久这里只精品99re66 | 国产高清视频在线免费观看 | 黄色毛片视频 | 一级毛片特级毛片免费的 | aaa特级毛片 | 亚洲一区天堂 | 天天干天天舔天天射 | 国产在线精品香蕉综合网一区 | 精品久久久久久久一区二区手机版 | 毛片免费全部播放一级 | 香蕉成人在线视频 | 深夜影院a | 亚洲视频在线播放 | 久久久夜间小视频 | 午夜欧美日韩 | 亚洲人成网站999久久久综合 | 操美女免费看 | 久久精品最新免费国产成人 | 91久久国产综合精品女同国语 | 91啦丨国产丨 | 欧美日韩综合在线视频免费看 | 日韩爱爱 | 成年女人毛片免费播放视频m | m3u8久久国产精品影院 | 一级一级一级一级毛片 | 色狠狠狠色噜噜噜综合网 | 亚洲国产系列久久精品99人人 | 天天看天天射天天碰 | 亚洲欧美日韩一级特黄在线 | 国产成人精品一区二区仙踪林 | 精品国产免费第一区二区三区日韩 | 天天干天天色天天干 | 破外女出血一级毛片 |