1. 程式人生 > 實用技巧 >python之單例模式

python之單例模式

在說單例模式前我們先看python在對類物件例項化及呼叫時都做了什麼?

python在對類物件例項化及呼叫時用到了__init__和__new__方法。下面首先通過__init__和__new__方法的呼叫來了解這一過程。

一、__new__和__init__的區別

  • __new__的作用:建立物件、分配記憶體
  • __init__的作用:初始化物件

程式碼演示如下:

#__new__和__init__的區別
#
先通過__new__建立物件,分配記憶體,然後使用__init__初始化物件 #所有的類都繼承於object,__new__屬於object中的方法。 # 呼叫我們平時定義的類時會自動的執行object類中的__new__方法建立物件,分配記憶體。
#下面將__new__ 方法重寫後,可以看到從建立物件到初始化的全過程 class myclass(object): def __init__(self): #初始化物件 print('initialization') def __new__(cls, *args, **kwargs): print('Create object,assign memory') obj = super().__new__(cls) ##建立物件、分配記憶體 return obj def add(self,a ,b):
return a + b if __name__ == '__main__': A = myclass()
  print(A.add(2,3))

執行結果:

Create object,assign memory
initialization
5

以上結果可以看出,先執行__new__進行物件的建立和記憶體的分配,然後在用__init__進行初始化操作。

二、使用__new__實現單例模式

單例模式是什麼?單例模式是指類有且僅有一個例項。

看下面的例子:

class myclass(object):
    def __init__(self):
        print
('多例項') class singleton(object): """ 通過__new__方法實現單例模式 實現思路: 如果未建立物件,就建立物件並返回,如果已經建立物件則直接返回已建立的物件 """ obj = None def __new__(cls, *args, **kwargs): if cls.obj is None: cls.obj = super().__new__(cls) return cls.obj if __name__ == '__main__': print('------多例項------') A = myclass() B = myclass() print(id(A)) print(id(B)) print('------單例項------') C = singleton() D = singleton() print(id(C)) print(id(D))

返回結果:

------多例項------
多例項
多例項
2266588874176
2266587884008
------單例項------
2266591390184
2266591390184

通過上面的多例項和單例項的對比,能很清楚的明白單例項。

三、裝飾器實現單例模式

通過裝飾器實現單例模式,能方便的在大量需要單例模式的時候直接應用

"""
通過裝飾器實現單例模式
"""


def singleton(cls):
    obj = {}
    def wrapper(*args,**kwargs):
        if not obj :
            obj[cls] = cls(*args,**kwargs)  ##obj字典中的鍵是類名,值為物件
        return obj[cls]
    return wrapper



@singleton
class myclass(object):
    pass

if __name__ == '__main__':
    A = myclass()
    print(id(A))
    B = myclass()
    print(id(B))

結果如下:

1961581206664
1961581206664

四、類方法實現單例、多例共有模式

  可以通過類方法實現一個類的單例建立物件和多例建立物件共存的模式,如下:

class mysgl(object):
    """
    類方法實現單例、雙例共有模式

    通過類方法建立的物件為單例模式
    通過例項建立物件為多例模式
    """
    __instance = {}
    def __init__(self, *args, **kwargs):
        pass

    @classmethod
    def singleton(cls, *args, **kwargs):
        if not cls.__instance:
            cls.__instance[cls] = cls(*args,**kwargs)
        return cls.__instance[cls]


if __name__ == '__main__':
    print('------類方法建立物件為單例物件------')
    A = mysgl.singleton()
    B = mysgl.singleton()
    print(id(A))
    print(id(B))
    print('------類例項建立物件為多例物件------')
    C = mysgl()
    D = mysgl()
    print(id(C))
    print(id(D))

結果如下:

------類方法建立物件為單例物件------
2725714123912
2725714123912
------類例項建立物件為多例物件------
2725714094400
2725745912296

五、建立執行緒安全的單例模式