成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

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

Maxiye / 2683人閱讀

摘要:本篇文章總結(jié)了目前主流的實(shí)現(xiàn)單例模式的方法供讀者參考。使用實(shí)現(xiàn)單例模式同樣,我們?cè)陬惖膭?chuàng)建時(shí)進(jìn)行干預(yù),從而達(dá)到實(shí)現(xiàn)單例的目的。

很多初學(xué)者喜歡用 全局變量 ,因?yàn)檫@比函數(shù)的參數(shù)傳來傳去更容易讓人理解。確實(shí)在很多場(chǎng)景下用全局變量很方便。不過如果代碼規(guī)模增大,并且有多個(gè)文件的時(shí)候,全局變量就會(huì)變得比較混亂。你可能不知道在哪個(gè)文件中定義了相同類型甚至重名的全局變量,也不知道這個(gè)變量在程序的某個(gè)地方被做了怎樣的操作。

因此對(duì)于這種情況,有種更好的實(shí)現(xiàn)方式:
單例(Singleton)

單例是一種 設(shè)計(jì)模式 ,應(yīng)用該模式的類只會(huì)生成一個(gè)實(shí)例。

單例模式保證了在程序的不同位置都 可以且僅可以取到同一個(gè)對(duì)象實(shí)例 :如果實(shí)例不存在,會(huì)創(chuàng)建一個(gè)實(shí)例;如果已存在就會(huì)返回這個(gè)實(shí)例。因?yàn)閱卫且粋€(gè)類,所以你也可以為其提供相應(yīng)的操作方法,以便于對(duì)這個(gè)實(shí)例進(jìn)行管理。

舉個(gè)例子來說,比如你開發(fā)一款游戲軟件,游戲中需要有“場(chǎng)景管理器”這樣一種東西,用來管理游戲場(chǎng)景的切換、資源載入、網(wǎng)絡(luò)連接等等任務(wù)。這個(gè)管理器需要有多種方法和屬性,在代碼中很多地方會(huì)被調(diào)用,且被調(diào)用的必須是同一個(gè)管理器,否則既容易產(chǎn)生沖突,也會(huì)浪費(fèi)資源。這種情況下,單例模式就是一個(gè)很好的實(shí)現(xiàn)方法。

單例模式廣泛應(yīng)用于各種開發(fā)場(chǎng)景,對(duì)于開發(fā)者而言是必須掌握的知識(shí)點(diǎn),同時(shí)在很多面試中,也是常見問題。本篇文章總結(jié)了目前主流的實(shí)現(xiàn)單例模式的方法供讀者參考。

希望看過此文的同學(xué),在以后被面到此問題時(shí),能直接皮一下面試官,“我會(huì) 4 種單例模式實(shí)現(xiàn),你想聽哪一種?”

以下是實(shí)現(xiàn)方法索引:

使用函數(shù)裝飾器實(shí)現(xiàn)單例

使用類裝飾器實(shí)現(xiàn)單例

使用 new 關(guān)鍵字實(shí)現(xiàn)單例

使用 metaclass 實(shí)現(xiàn)單例

使用函數(shù)裝飾器實(shí)現(xiàn)單例

以下是實(shí)現(xiàn)代碼:


def singleton(cls):
    _instance = {}

    def inner():
        if cls not in _instance:
            _instance[cls] = cls()
        return _instance[cls]
    return inner
    
@singleton
class Cls(object):
    def __init__(self):
        pass

cls1 = Cls()
cls2 = Cls()
print(id(cls1) == id(cls2))

輸出結(jié)果:


True

在 Python 中,id 關(guān)鍵字可用來查看對(duì)象在內(nèi)存中的存放位置,這里 cls1 和 cls2 的 id 值相同,說明他們指向了同一個(gè)對(duì)象。

關(guān)于裝飾器的知識(shí),有不明白的同學(xué)可以查看之前的文章 【編程課堂】裝飾器淺析 或者使用搜索引擎再學(xué)習(xí)一遍。代碼中比較巧妙的一點(diǎn)是:


_instance = {}

使用不可變的 類地址 作為鍵,其實(shí)例作為值,每次創(chuàng)造實(shí)例時(shí),首先查看該類是否存在實(shí)例,存在的話直接返回該實(shí)例即可,否則新建一個(gè)實(shí)例并存放在字典中。

使用類裝飾器實(shí)現(xiàn)單例

代碼:


class Singleton(object):
    def __init__(self, cls):
        self._cls = cls
        self._instance = {}
    def __call__(self):
        if self._cls not in self._instance:
            self._instance[self._cls] = self._cls()
        return self._instance[self._cls]

@Singleton
class Cls2(object):
    def __init__(self):
        pass

cls1 = Cls2()
cls2 = Cls2()
print(id(cls1) == id(cls2))

同時(shí),由于是面對(duì)對(duì)象的,這里還可以這么用


class Cls3():
    pass

Cls3 = Singleton(Cls3)
cls3 = Cls3()
cls4 = Cls3()
print(id(cls3) == id(cls4))

使用 類裝飾器實(shí)現(xiàn)單例的原理和 函數(shù)裝飾器 實(shí)現(xiàn)的原理相似,理解了上文,再理解這里應(yīng)該不難。

New、Metaclass 關(guān)鍵字

在接著說另外兩種方法之前,需要了解在 Python 中一個(gè)類和一個(gè)實(shí)例是通過哪些方法以怎樣的順序被創(chuàng)造的。

簡(jiǎn)單來說, 元類 ( metaclass ) 可以通過方法 metaclass 創(chuàng)造了 類(class) ,而 類(class) 通過方法 new 創(chuàng)造了 實(shí)例(instance) 。

在單例模式應(yīng)用中,在創(chuàng)造類的過程中或者創(chuàng)造實(shí)例的過程中稍加控制達(dá)到最后產(chǎn)生的實(shí)例都是一個(gè)對(duì)象的目的。

本文主講單例模式,所以對(duì)這個(gè) topic 只會(huì)點(diǎn)到為止,有感興趣的同學(xué)可以在網(wǎng)上搜索相關(guān)內(nèi)容,幾篇參考文章:

What are metaclasses in Python?

https://stackoverflow.com/questions/100003/what-are-metaclasses-in-python

python-__new__-magic-method-explained

http://howto.lintel.in/python-__new__-magic-method-explained/

Why is __init__() always called after __new__()?

https://stackoverflow.com/questions/674304/why-is-init-always-called-after-new

使用 new 關(guān)鍵字實(shí)現(xiàn)單例模式

使用 new 方法在創(chuàng)造實(shí)例時(shí)進(jìn)行干預(yù),達(dá)到實(shí)現(xiàn)單例模式的目的。


class Single(object):
    _instance = None
    def __new__(cls, *args, **kw):
        if cls._instance is None:
            cls._instance = object.__new__(cls, *args, **kw)
        return cls._instance
    def __init__(self):
        pass

single1 = Single()
single2 = Single()
print(id(single1) == id(single2))

在理解到 new 的應(yīng)用后,理解單例就不難了,這里使用了


_instance = None

來存放實(shí)例,如果 _instance 為 None,則新建實(shí)例,否則直接返回 _instance 存放的實(shí)例。

使用 metaclass 實(shí)現(xiàn)單例模式

同樣,我們?cè)陬惖膭?chuàng)建時(shí)進(jìn)行干預(yù),從而達(dá)到實(shí)現(xiàn)單例的目的。

在實(shí)現(xiàn)單例之前,需要了解使用 type 創(chuàng)造類的方法,代碼如下:


def func(self):
    print("do sth")

Klass = type("Klass", (), {"func": func})

c = Klass()
c.func()

以上,我們使用 type 創(chuàng)造了一個(gè)類出來。這里的知識(shí)是 mataclass 實(shí)現(xiàn)單例的基礎(chǔ)。


class Singleton(type):
    _instances = {}
    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
        return cls._instances[cls]

class Cls4(metaclass=Singleton):
    pass

cls1 = Cls4()
cls2 = Cls4()
print(id(cls1) == id(cls2))

這里,我們將 metaclass 指向 Singleton 類,讓 Singleton 中的 type 來創(chuàng)造新的 Cls4 實(shí)例。

小結(jié)

本文雖然是講單例模式,但在實(shí)現(xiàn)單例模式的過程中,涉及到了蠻多高級(jí) Python 語法,包括裝飾器、元類、new、type 甚至 super 等等。對(duì)于新手同學(xué)可能難以理解,其實(shí)在工程項(xiàng)目中并不需要你掌握的面面俱到,掌握其中一種,剩下的作為了解即可。

by 周鑫鑫

關(guān)于更多的設(shè)計(jì)模式,給初學(xué)者推薦《 Head First 設(shè)計(jì)模式 》(Head First Design Patterns),此書淺顯易懂,在 Head First 系列書籍里面也算是很好的一本。

我們的資源網(wǎng)盤里有電子版,獲取地址請(qǐng)?jiān)诠娞?hào)( Crossin的編程教室 )里回復(fù)關(guān)鍵字: 資源

════
其他文章及回答:

如何自學(xué)Python | 新手引導(dǎo) | 精選Python問答 | Python單詞表 | 區(qū)塊鏈 | 人工智能 | 雙11 | 嘻哈 | 爬蟲 | 排序算法

歡迎搜索及關(guān)注: Crossin的編程教室

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/42490.html

相關(guān)文章

  • Python new 類方法和 init 實(shí)例方法以及單例模式簡(jiǎn)單討論

    摘要:中的類都是單例模式一天,一同事問我這樣一個(gè)問題。與方法屬于新式類,即屬于類。方法在實(shí)例被創(chuàng)建之后被調(diào)用,該方法僅僅是對(duì)方法創(chuàng)建的實(shí)例進(jìn)行一些初始化操作。需要注意的是,在重寫方法與方法的參數(shù)應(yīng)該保持一致,否則會(huì)有發(fā)生。 Python 中的類都是單例模式? 一天,一同事問我這樣一個(gè)問題。這是一個(gè)奇怪的問題,可能你也這么認(rèn)為。這里先不做解釋,我們先來看看 __new__ 和 __init__...

    FingerLiu 評(píng)論0 收藏0
  • Python實(shí)現(xiàn)設(shè)計(jì)模式——單例模式

    摘要:前言單例模式是設(shè)計(jì)模式中最簡(jiǎn)單最容易理解的一種,維基百科的定義如下單例模式,也叫單子模式,是一種常用的軟件設(shè)計(jì)模式。 前言 單例模式是設(shè)計(jì)模式(Design Pattern)中最簡(jiǎn)單、最容易理解的一種,維基百科[1]的定義如下: 單例模式,也叫單子模式,是一種常用的軟件設(shè)計(jì)模式。在應(yīng)用這個(gè)模式時(shí),單例對(duì)象的類 類 (計(jì)算機(jī)科學(xué)))必須保證只有一個(gè)實(shí)例存在。許多時(shí)候整個(gè)系統(tǒng)只需要擁有一...

    CollinPeng 評(píng)論0 收藏0
  • Python單例模式

    摘要:在中,我們可以用多種方法來實(shí)現(xiàn)單例模式使用模塊使用使用裝飾器使用元類使用模塊其實(shí),的模塊就是天然的單例模式,因?yàn)槟K在第一次導(dǎo)入時(shí),會(huì)生成文件,當(dāng)?shù)诙螌?dǎo)入時(shí),就會(huì)直接加載文件,而不會(huì)再次執(zhí)行模塊代碼。 單例模式 單例模式(Singleton Pattern)是一種常用的軟件設(shè)計(jì)模式,該模式的主要目的是確保某一個(gè)類只有一個(gè)實(shí)例存在。當(dāng)你希望在整個(gè)系統(tǒng)中,某個(gè)類只能出現(xiàn)一個(gè)實(shí)例時(shí),單例對(duì)...

    khlbat 評(píng)論0 收藏0
  • Python單例模式

    摘要:使用元類可以控制類的創(chuàng)建過程,它主要做三件事攔截類的創(chuàng)建修改類的定義返回修改后的類使用元類實(shí)現(xiàn)單例模式的代碼如下執(zhí)行結(jié)果 單例模式 單例模式(Singleton Pattern)是一種常用的軟件設(shè)計(jì)模式,該模式的主要目的是確保某一個(gè)類只有一個(gè)實(shí)例存在。當(dāng)你希望在整個(gè)系統(tǒng)中,某個(gè)類只能出現(xiàn)一個(gè)實(shí)例時(shí),單例對(duì)象就能派上用場(chǎng)。 比如,某個(gè)服務(wù)器程序的配置信息存放在一個(gè)文件中,客戶端通過一個(gè) ...

    church 評(píng)論0 收藏0
  • 每天一個(gè)設(shè)計(jì)模式單例模式

    摘要:博主按每天一個(gè)設(shè)計(jì)模式旨在初步領(lǐng)會(huì)設(shè)計(jì)模式的精髓,目前采用靠這吃飯和純粹喜歡兩種語言實(shí)現(xiàn)。單例模式用途如果一個(gè)類負(fù)責(zé)連接數(shù)據(jù)庫的線程池日志記錄邏輯等等,此時(shí)需要單例模式來保證對(duì)象不被重復(fù)創(chuàng)建,以達(dá)到降低開銷的目的。 博主按:《每天一個(gè)設(shè)計(jì)模式》旨在初步領(lǐng)會(huì)設(shè)計(jì)模式的精髓,目前采用javascript(_靠這吃飯_)和python(_純粹喜歡_)兩種語言實(shí)現(xiàn)。誠然,每種設(shè)計(jì)模式都有多種實(shí)...

    yy736044583 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<