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

資訊專欄INFORMATION COLUMN

python設(shè)計(jì)模式-單例模式

darkbug / 719人閱讀

摘要:實(shí)現(xiàn)實(shí)現(xiàn)單例模式有多種方案使用提供了非常易用的類,只要繼承它,就會(huì)成為單例。參考鏈接單例模式最后,感謝女朋友支持。

問(wèn)題:現(xiàn)代化的巧克力工廠具備計(jì)算機(jī)控制的巧克力鍋爐。鍋爐做的事情就是把巧克力和牛奶融在一起,然后送到下一個(gè)階段,以制成巧克力棒。下邊是一個(gè)巧克力公司鍋爐控制器的代碼,仔細(xì)觀察一下,這段代碼有什么問(wèn)題?

class ChocolateBoiler(object):

    def __init__(self):
        self.empty = True
        self.boiled = False

    def fill(self):
        # 向鍋爐填充巧克力和牛奶混合物
        # 在鍋爐內(nèi)填充原料時(shí),鍋爐必須是空的。
        # 一旦填入原料,就要把empty 和 boiled 標(biāo)志設(shè)置好
        if self.empty:
            self.empty = False
            self.boiled = False

    def drain(self):
        # 排出煮沸的巧克力和牛奶
        # 鍋爐排出時(shí),必須是滿的且煮沸的。
        # 排出完畢empty 設(shè)置為 true
        if not self.empty and self.boiled:
            self.empty = True

    def boil(self):
        # 將顱內(nèi)物煮沸
        # 煮混合物時(shí),鍋爐內(nèi)必須是滿的且沒(méi)有煮沸過(guò)
        # 一旦煮沸,就把 boiled 設(shè)置為 true
        if not self.empty and not self.boiled:
            self.boiled = True

從代碼可以看出,他們加入了多種判斷,以防止不好的事情發(fā)生。如果同時(shí)存在兩個(gè)ChocolateBoiler實(shí)例,那這么多判斷豈不是失去作用了。那我們改如何實(shí)現(xiàn)這個(gè)需求呢?這個(gè)問(wèn)題的核心是,我們要先判斷實(shí)例是不是已經(jīng)存在,如果存在就不再創(chuàng)建。

_chocolate_boiler_instance = None  # 聲明實(shí)例

def chocolate_boiler():
    global _chocolate_boiler_instance  # 使用全局變量

    if _chocolate_boiler_instance is not None: # 判斷是否存在,如果存在,直接返回
        return _chocolate_boiler_instance
    else:
        # 如果不存在,創(chuàng)建一個(gè)新的
        _chocolate_boiler_instance = ChocolateBoiler()
        return _chocolate_boiler_instance

現(xiàn)在我們需要獲取 ChocolateBoiler 實(shí)例的時(shí)候只需要調(diào)用 chocolate_boiler 方法獲取實(shí)例即可保證同時(shí)只有一個(gè) ChocolateBoiler實(shí)例。

這種保證 ChocolateBoiler類只有一個(gè)實(shí)例,并提供一個(gè)全局訪問(wèn)點(diǎn)的模式,就是單例模式

單例模式 定義

單例模式:確保一個(gè)類只有一個(gè)實(shí)例,并提供一個(gè)全局訪問(wèn)點(diǎn)。

也就是說(shuō),我們使用單例模式要把某個(gè)類設(shè)計(jì)成自己管理的一個(gè)多帶帶實(shí)例,同時(shí)也避免其他類再自行產(chǎn)生實(shí)例。并且只允許通過(guò)單例類獲取單例的實(shí)例。

我們也提供對(duì)這個(gè)實(shí)例的全局訪問(wèn)點(diǎn):當(dāng)你需要實(shí)例時(shí),像類查詢,它會(huì)返回單個(gè)實(shí)例。

實(shí)現(xiàn)

python 實(shí)現(xiàn)單例模式有多種方案:

使用 metaclass

《python cookbook》提供了非常易用的 Singleton 類,只要繼承它,就會(huì)成為單例。

# python 3 代碼實(shí)現(xiàn)
class Singleton(type):

    def __init__(self, *args, **kwargs):
        self.__instance = None
        super().__init__(*args, **kwargs)

    def __call__(self, *args, **kwargs):
        if self.__instance is None:
            # 如果 __instance 不存在,創(chuàng)建新的實(shí)例
            self.__instance = super().__call__(*args, **kwargs)
            return self.__instance
        else:
            # 如果存在,直接返回
            return self.__instance


class Spam(metaclass=Singleton):

    def __init__(self):
        print("Creating Spam")

a = Spam()
b = Spam()

print(a is b)  # 這里輸出為 True

元類(metaclass)可以控制類的創(chuàng)建過(guò)程,它主要做三件事:

攔截類的創(chuàng)建

修改類的定義

返回修改后的類

例子中我們構(gòu)造了一個(gè)Singleton元類,并使用__call__方法使其能夠模擬函數(shù)的行為。構(gòu)造類 Spam 時(shí),將其元類設(shè)為Singleton,那么創(chuàng)建類對(duì)象 Spam 時(shí),行為發(fā)生如下:

Spam = Singleton(name,bases,class_dict),Spam 其實(shí)為Singleton類的一個(gè)實(shí)例。

創(chuàng)建 Spam 的實(shí)例時(shí),Spam()=Singleton(name,bases,class_dict)()=Singleton(name,bases,class_dict).__call__(),這樣就將 Spam 的所有實(shí)例都指向了 Spam 的屬性 __instance上。

使用 new

我們可以使用 new 來(lái)控制實(shí)例的創(chuàng)建過(guò)程,代碼如下:

class Singleton(object):

    __instance = None

    def __new__(cls, *args, **kw):
        if not cls.__instance:
            cls.__instance = super().__new__(cls, *args, **kw)
        return cls.__instance

class Foo(Singleton):
    a = 1

one = Foo()
two = Foo()
assert one == two
assert one is two
assert id(one) == id(two)

通過(guò) new 方法,將類的實(shí)例在創(chuàng)建的時(shí)候綁定到類屬性 __instance 上。如果cls.__instance 為None,說(shuō)明類還未實(shí)例化,實(shí)例化并將實(shí)例綁定到cls.__instance 以后每次實(shí)例化的時(shí)候都返回第一次實(shí)例化創(chuàng)建的實(shí)例。注意從Singleton派生子類的時(shí)候,不要重載__new__。

使用裝飾器
import functools

def singleton(cls):
    """ Use class as singleton. """
    # 首先將 __new__ 方法賦值給 __new_original__
    cls.__new_original__ = cls.__new__

    @functools.wraps(cls.__new__)
    def singleton_new(cls, *args, **kw):
        # 嘗試從 __dict__ 取 __it__
        it =  cls.__dict__.get("__it__")
        if it is not None: # 如果有值,說(shuō)明實(shí)例已經(jīng)創(chuàng)建,返回實(shí)例
            return it
        # 如果實(shí)例不存在,使用 __new_original__ 創(chuàng)建實(shí)例,并將實(shí)例賦值給 __it__
        cls.__it__ = it = cls.__new_original__(cls, *args, **kw)
        it.__init_original__(*args, **kw)
        return it
    # class 將原有__new__ 方法用 singleton_new 替換
    cls.__new__ = singleton_new
    cls.__init_original__ = cls.__init__
    cls.__init__ = object.__init__

    return cls

#
# 使用示例
#
@singleton
class Foo:
    def __new__(cls):
        cls.x = 10
        return object.__new__(cls)

    def __init__(self):
        assert self.x == 10
        self.x = 15


assert Foo().x == 15
Foo().x = 20
assert Foo().x == 20

這種方法的內(nèi)部實(shí)現(xiàn)和使用 __new__ 類似:

首先,將 new 方法賦值給 new_original__,原有 new 方法用 singleton_new 替換,定義 init_original 并將 cls.__init 賦值給 init_original

在 singleton_new 方法內(nèi)部,嘗試從 dict 取 __it__(實(shí)例)

如果實(shí)例不存在,使用 new_original 創(chuàng)建實(shí)例,并將實(shí)例賦值給 __it__,然后返回實(shí)例

最簡(jiǎn)單的方式

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

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

https://github.com/gusibi/Metis/blob/master/apis/v1/schemas.py#L107 使用的就是這種方式,用來(lái)獲取全局的 request

Python 的模塊就是天然的單例模式,因?yàn)槟K在第一次導(dǎo)入時(shí),會(huì)生成 .pyc 文件,當(dāng)?shù)诙螌?dǎo)入時(shí),就會(huì)直接加載 .pyc 文件,而不會(huì)再次執(zhí)行模塊代碼。因此,我們只需把相關(guān)的函數(shù)和數(shù)據(jù)定義在一個(gè)模塊中,就可以獲得一個(gè)單例對(duì)象了。

參考鏈接

Creating a singleton in Python

Python單例模式

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


最后,感謝女朋友支持。

歡迎關(guān)注(April_Louisa) 請(qǐng)我喝芬達(dá)

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

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

相關(guān)文章

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

    摘要:本篇文章總結(jié)了目前主流的實(shí)現(xiàn)單例模式的方法供讀者參考。使用實(shí)現(xiàn)單例模式同樣,我們?cè)陬惖膭?chuàng)建時(shí)進(jìn)行干預(yù),從而達(dá)到實(shí)現(xiàn)單例的目的。 很多初學(xué)者喜歡用 全局變量 ,因?yàn)檫@比函數(shù)的參數(shù)傳來(lái)傳去更容易讓人理解。確實(shí)在很多場(chǎng)景下用全局變量很方便。不過(guò)如果代碼規(guī)模增大,并且有多個(gè)文件的時(shí)候,全局變量就會(huì)變得比較混亂。你可能不知道在哪個(gè)文件中定義了相同類型甚至重名的全局變量,也不知道這個(gè)變量在程序的某...

    Maxiye 評(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 中的單例模式

    摘要:在中,我們可以用多種方法來(lái)實(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)建過(guò)程,它主要做三件事攔截類的創(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è)文件中,客戶端通過(guò)一個(gè) ...

    church 評(píng)論0 收藏0
  • Python設(shè)計(jì)模式

    摘要:簡(jiǎn)單工廠模式工廠模式有一種非常形象的描述,建立對(duì)象的類就如一個(gè)工廠,而需要被建立的對(duì)象就是一個(gè)個(gè)產(chǎn)品在工廠中加工產(chǎn)品,使用產(chǎn)品的人,不用在乎產(chǎn)品是如何生產(chǎn)出來(lái)的。單例模式的單例模式,所謂單例模式就是一個(gè)類只能創(chuàng)建一個(gè)實(shí)例化。 簡(jiǎn)單工廠模式 工廠模式有一種非常形象的描述,建立對(duì)象的類就如一個(gè)工廠,而需要被建立的對(duì)象就是一個(gè)個(gè)產(chǎn)品;在工廠中加工產(chǎn)品,使用產(chǎn)品的人,不用在乎產(chǎn)品是如何生產(chǎn)出來(lái)...

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

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

0條評(píng)論

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