python的單例模式和__new__方法


單例模式是一個常用的軟件設計模式,該模式的主要目的是確保某一個類只有一個實例存在。比如說:利用加標簽的白名單防止跨站腳本攻擊XXS創建一個XxsFile類,不同的人訪問都要創建XxsFile對象的實例,這就導致系統中存在多個XxsFile的實例對象,而這樣會嚴重浪費內存資源。事實上類似於XxsFile這樣的類,我們希望在程序運行期間只存在一個實例對象,在python中,我們可以使用單例。如下列幾種方法:


在Python中new方法和init方法類似,但是如果兩個都存在那么new先執行

__new__(cls, *args, **kwargs)

__new__()中的需要傳遞一個參數cls,cls表示需要實例化的類,此參數在實例化時由Python解析器自動提供

1、類方法classmethod

# -*-coding:utf-8 -*-
class Foo(object):
    __instance = None

    @classmethod
    def instance(self):
        if self.__instance:
            return self.__instance

        else:
            obj = self()
            self.__instance = obj
            return self.__instance
obj1=Foo.instance()
obj2=Foo.instance()
print(obj1,obj2)

2、基於__new__方法實現(推薦使用、方便)

當我們實例化一個對象時,是先執行了類的__new__方法(當我們沒寫時,默認調用object.__new__),實例化對象;然后再執行類的__init__方法,對這個對象進行初始化,所以我們可以基於這個,實現單例模式:

# -*-coding:utf-8 -*-
class Foo(object):
    __instance=None
    def __init__(self):
        pass
    def __new__(cls, *args, **kwargs):

        if cls.__instance:
            return cls.__instance
        else:
            obj = object.__new__(cls,*args,**kwargs)
            cls.__instance = obj
            return cls.__instance
obj1=Foo()
obj2=Foo()
print(obj1,obj2)

Python new()方法,為對象分配內存,返回對象的引用

# -*-coding:utf-8 -*-
class MusicPlayer(object):

    #為對象分配內存空間
    def __new__(cls, *args, **kwargs):

        #1、創建對象時,new方法會被自動調用
        print("創建對象,分配內存空間")

        #2、為對象分配空間
        instance = super().__new__(cls)

        #3、返回對象引用
        return instance
    #對象初始化,定義實例屬性
    def __init__(self):
        print("播放器初始化")

#創建播放器對象
player = MusicPlayer()
print(player)

__new__方法:

使用MusicPlayer()創建對象時,python的解釋器首先會調用__new__方法為對象分配空間,如果不分配空間那么就不會調用初始化__init____new__是一個由object基類提供的內置的靜態方法,主要作用有兩個:

1、在內存空間中為對象分配空間

2、返回對象的引用

Python的解釋器獲取得到對象的引用后,將引用作為第一個參數,傳遞給__init__,

1、重寫__new__方法python用return super().__new__(cls),否則Python的解釋器得不到分配了空間的對象引用,就不會調用對象的初始化方法,注意:__new__是一個靜態方法,在調用時需要主動傳遞cls參數

如果分配了內存空間,就會調用初始化__init__的結果:

# -*-coding:utf-8 -*-
class MusicPlayer(object):

    #為對象分配內存空間
    def __new__(cls, *args, **kwargs):

        #1、創建對象時,new方法會被自動調用
        print("創建對象,分配內存空間")

        #2、為對象分配空間
        instance = super().__new__(cls)

        #3、返回對象引用
        return instance
    #對象初始化,定義實例屬性
    def __init__(self):
        print("播放器初始化")

#創建播放器對象
player = MusicPlayer()
print(player)

#輸出:
    # 創建對象,分配內存空間
    # 播放器初始化
    # <__main__.MusicPlayer object at 0x033D09B0>

如果__new__不分配內存空間,創建對象的時候就不會去的調用__init__,結果如下:

    # -*-coding:utf-8 -*-
class MusicPlayer(object):

    #為對象分配內存空間
    def __new__(cls, *args, **kwargs):

        #1、創建對象時,new方法會被自動調用
        print("創建對象,分配內存空間")

        
    #對象初始化,定義實例屬性
    def __init__(self):
        print("播放器初始化")

#創建播放器對象
player = MusicPlayer()
print(player)

#輸出:
    #創建對象,分配內存空間
    #None


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM