Python單例模式的實現方式
所謂單例,是指一個類的例項從始至終只能被建立一次。
方法1:使用new方法
如果想使得某個類從始至終最多隻有一個例項,使用new方法會很簡單。Python中類是通過new來建立例項的:
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
結果:
29922256 banana
29922256 banana
通過new方法,將類的例項在建立的時候繫結到類屬性_inst上。如果cls._inst為None,說明類還未例項化,例項化並將例項繫結到cls._inst,以後每次例項化的時候都返回第一次例項化建立的例項。注意從Singleton派生子類的時候,不要過載new。
方法2:
有時候我們並不關心生成的例項是否具有同一id,而只關心其狀態和行為方式。我們可以允許許多個例項被建立,但所有的例項都共享狀態和行為方式:
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
將所有例項的dict指向同一個字典,這樣例項就共享相同的方法和屬性。對任何例項的名字屬性的設定,無論是在init中修改還是直接修改,所有的例項都會受到影響。不過例項的id是不同的。要保證類例項能共享屬性,但不和子類共享,注意使用cls._shared_state,而不是Borg._shared_state。
因為例項是不同的id,所以每個例項都可以做字典的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]
結果:
0
1
2
如果這種行為不是你想要的,可以為Borg類新增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]
結果:
2
2
2
所有的例項都能當一個key使用了。
方法3: 元類metaclass
當你編寫一個類的時候,某種機制會使用類名字,基類元組,類字典來建立一個類物件。新型類中這種機制預設為type,而且這種機制是可程式設計的,稱為元類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)
結果:
34248016 34248016
id是相同的。
例子中我們構造了一個Singleton元類,並使用__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的屬性_instance上,這種方法與方法1其實是相同的。
方法4
python中的模組module在程式中只被載入一次,本身就是單例的。可以直接寫一個模組,將你需要的方法和屬性,寫在模組中當做函式和模組作用域的全域性變數即可,根本不需要寫類。
而且還有一些綜合模組和類的優點的方法:
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並不會對sys.modules進行檢查以確保他們是模組物件,我們利用這一點將模組繫結向一個類物件,而且以後都會繫結向同一個物件了。
將程式碼存放在single.py中:
>>> import single
>>> single.a=1
>>> single.a=2
ConstError
>>> del single.a
ConstError
方法5:
最簡單的方法:
class singleton(object):
pass
singleton=singleton()
將名字singleton繫結到例項上,singleton就是它自己類的唯一物件了。
相關文章
- 單例模式:5種實現方式單例模式
- 單例模式的各種實現方式(Java)單例模式Java
- 五種方式實現 Java 單例模式Java單例模式
- Python中實現單例模式Python單例模式
- Python中的單例模式的幾種實現方式的及優化Python單例模式優化
- Java設計模式——實現單例模式的七種方式[JZOF]Java設計模式單例
- 在Python中實現單例模式Python單例模式
- 單例模式的實現單例模式
- 用Python實現設計模式——單例模式Python設計模式單例
- 設計模式學習(一)單例模式的幾種實現方式設計模式單例
- Python 建立單例模式的三種方式Python單例模式
- JAVA中實現單例(Singleton)模式的八種方式Java單例模式
- 單例模式的五種實現方式及優缺點單例模式
- Python 5種方法實現單例模式Python單例模式
- 【設計模式】實現執行緒安全單例模式的五種方式設計模式執行緒單例
- Python單例模式(Singleton)的N種實現Python單例模式
- Java單例設計模式的理解與常規實現方式Java單例設計模式
- 美團一面:會單例模式嗎,寫個單例看看?(8大單例模式實現方式總結)單例模式
- JS中的單例模式及單例模式原型類的實現JS單例模式原型
- DCL單例模式中的缺陷及單例模式的其他實現單例模式
- Python 實現工廠模式、抽象工廠,單例模式Python模式抽象單例
- PHP實現單例模式PHP單例模式
- golang實現單例模式Golang單例模式
- Javascript實現單例模式JavaScript單例模式
- Rust實現單例模式Rust單例模式
- C++用多種方式實現Singleton單例模式C++單例模式
- 單例模式的各種實現單例模式
- python如何實現單例模式?常用方法彙總!Python單例模式
- 單例模式實現對比單例模式
- Kotlin實現單例模式Kotlin單例模式
- C++實現單例模式C++單例模式
- 單例模式c++實現單例模式C++
- 設計模式-Java實現單例模式設計模式Java單例
- 單例模式的 Java 實現與思考單例模式Java
- 設計模式學習筆記(四)單例模式的實現方式和使用場景設計模式筆記單例
- 設計模式:單例模式的使用和實現(JAVA)設計模式單例Java
- 【php實現設計模式】之單例模式PHP設計模式單例
- 設計模式——單例模式C++實現設計模式單例C++