所謂單例,是指一個類別的實例從頭到尾只能被創建一次。
方法1
如果想使得某個類別從始至終最多只有一個實例,使用__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
類別屬性_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
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]
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]
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)
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()
>>> import single >>> single.a=1 >>> single.a=2
class singleton(object): pass singleton=singleton()
將名字singleton綁定到實例上,singleton就是它自己類別的唯一物件了。