您好,登錄后才能下訂單哦!
本篇文章為大家展示了Python中什么是單例模式,代碼簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細(xì)介紹希望你能有所收獲。
python單例模式
單例模式是一種常用的軟件設(shè)計模式,在單例模式的核心結(jié)構(gòu)中,只包含一個被稱為單例類的特殊類。
通過單例模式可以保證系統(tǒng)中一個類只有一個實例,而且這個實例可以輕易被外界訪問,方便控制實例對象的個數(shù)以節(jié)約系統(tǒng)資源。
單例模式是解決一個系統(tǒng)中某個類的實例化對象有且只能有一個的最好解決方案。
單例模式的要點有三個:
(1)某個類只能有一個實例。
(2)這個類必須自行創(chuàng)建其唯一實例。
(3)這個類必須自行向整個系統(tǒng)提供這個唯一實例。
在python中,單例模式有三種實現(xiàn)方式:
方法一,使用__new__方法
先定義一個類,類中定義__new__方法,然后將類的一個實例類綁定到類變量中。
如果類的_instance值為None,則說明這個類還沒有被實例化過,程序會自動實例化一個類的實例,然后返回。
如果類的_instance值不為None,則程序會直接返回_instance。
代碼如下:
class Singleton(object): _instance = None def __init__(self): pass def __new__(cls, *args, **kwargs): if not cls._instance: cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs) return cls._instance class MyClass(Singleton): a = 1
在上面的代碼中,我們將類的實例和一個類變量 _instance關(guān)聯(lián)起來。
如果 cls._instance為 None 則創(chuàng)建實例,否則直接返回cls._instance。
用上來定義的類實例化兩個對象:
cls1=MyClass() cls2=MyClass() print(id(cls1)) print(id(cls2)) print(cls1 == cls2) print(cls1 is cls2)
得到的結(jié)果
43606480 43606480 True True
方法二,使用decorator裝飾器
我們知道,裝飾器(decorator)可以動態(tài)地修改一個類或函數(shù)的功能。
在這里使用裝飾器來裝飾某個類,使其只能生成一個實例,代碼如下:
def singleton(cls): instances={} def getinstance(*args,**kwargs): if cls not in instances: instances[cls]=cls(*args,**kwargs) return instances[cls] return getinstance @singleton class MyClass(object): a=1
在上面,我們定義了一個裝飾器singleton,它返回了一個內(nèi)部函數(shù)getinstance,該函數(shù)會判斷某個類是否在字典instances中,
如果不存在,則會將cls作為key,cls(*args, **kw)作為value存到instances中,否則,直接返回instances[cls]。
使用上面定義的類實例化兩個對象,比較兩個對象
cls1=MyClass() cls2=MyClass() print(id(cls1)) print(id(cls2)) print(cls1 == cls2) print(cls1 is cls2)
得到的結(jié)果為:
43672016 43672016 True True
方法三,使用元類(metaclass)
元類(metaclass)可以控制類的創(chuàng)建過程,它主要做三件事:
攔截類的創(chuàng)建 修改類的定義 返回修改后的類
用元類實現(xiàn)單例模式的代碼如下:
class Singleton(type): _inst = {} def __call__(self, *args, **kw): if self not in self._inst: self._inst[self] = super(Singleton, self).__call__(*args, **kw) return self._inst[self] class MyClass(metaclass=Singleton): def __init__(self): self.xx = 0 cls1=MyClass() cls2=MyClass() print(id(cls1)) print(id(cls2)) print(cls1 == cls2) print(cls1 is cls2)
得到的結(jié)果為:
43477984 43477984 True True
方法四,使用classmethod方法創(chuàng)建單例模式
class Foo: _instance = None def __init__(self): pass @classmethod def get_instance(cls): if cls._instance: return cls._instance else: obj=cls() cls._instance=obj return obj cls1=Foo.get_instance() # 實例化對象a1時,沒有執(zhí)行Foo這個類的__init__方法,直接執(zhí)行Foo類的get_instance方法, 在這里cls代指的是Foo類。 # 前面把_instance賦值為None,所以直接執(zhí)行else中的語句,實例化一個obj對象, 然后把obj對象中的_instance方法賦值為obj對象本身,然后返回obj對象。 cls2=Foo.get_instance() # 實例化a1時,Foo類中的_instance已經(jīng)被賦值為obj對象,所以再次執(zhí)行Foo中的get_instance方法時, 是執(zhí)行if中的語句。 # 此時cls._instance就指的是obj對象,所以這里也返回obj這個對象。 print(id(cls1)) print(id(cls2)) print(cls1 == cls2) print(cls1 is cls2)
這種方法由于在實例化對象時要調(diào)用類中的get_instance方法,所以用的不多,知道即可。
特別聲明
Python的模塊是天然的單例模式,在一個py文件中,多次導(dǎo)入同一個模塊,這個模塊也只有在第一次的時候被導(dǎo)入,后續(xù)的該模塊導(dǎo)入語句都不會再執(zhí)行了。
上述內(nèi)容就是Python中什么是單例模式,你們學(xué)到知識或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識儲備,歡迎關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。