天天看點

Python單執行個體模式

Python單執行個體

#1 環境

Python3.8.1           

複制

#2 什麼是單執行個體

單例模式就是確定一個類隻有一個執行個體.當你希望整個系統中,某個類隻有一個執行個體時,單例模式就派上了用場

#3 實作單執行個體方式

#3.1 非單執行個體

class MyClass(object):

    def foo(self):

        return None

obj1 = MyClass()
obj2 = MyClass()
print(obj1 is obj2)
print(id(obj1))
print(id(obj2))           

複制

#3.2 使用子產品

class MyClass(object):

    def foo(self):

        return None

obj = MyClass()           

複制

使用:

from singleton.mysingleton import obj           

複制

python的子產品就是天然的單例模式,因為子產品在第一次導入的時候,會生成.pyc檔案,當第二次導入的時候,就會直接加載.pyc檔案,而不是再次執行子產品代碼.如果我們把相關的函數和資料定義在一個子產品中,就可以獲得一個單例對象了

#3.3 使用裝飾器

def singleton(cls):
    """裝飾器函數"""

    class_instance = {} # 定義一個接受執行個體的類 

    def singleton_inner(*args, **kwargs):

        if cls not in class_instance: # 判斷該類是否被執行個體化過 
            class_instance[cls] = cls(*args, **kwargs) # 沒有被執行個體化過 -> 執行個體化 -> 将執行個體化的對象添加到字典中  

        return class_instance[cls] # 傳回執行個體化對象 

    return singleton_inner 

@singleton
class MyClass(object):

    def foo(self):

        return None

obj1 = MyClass()
obj2 = MyClass()
print(obj1 is obj2)
print(id(obj1))
print(id(obj2))           

複制

Python單執行個體模式

在類前加個裝飾器,在這裡裝飾器的目的隻有一個,就是在類執行個體化前,先判斷這個類有沒有執行個體化過,如果沒有,則執行個體化,如果執行個體化過,測傳回之前的執行個體化對象

#3.4 使用類

class MyClass(object):

    def foo(self):

        return None

    @classmethod
    def get_instance(cls, *args, **kwargs):
        """執行個體化函數"""

        if not hasattr(cls, '_instance'):
            cls._instance = cls(*args, **kwargs)

        return cls._instance


obj1 = MyClass.get_instance()
obj2 = MyClass.get_instance()
print(obj1 is obj2)
print(id(obj1))
print(id(obj2))
obj3 = MyClass()
print(id(obj3))           

複制

Python單執行個體模式

以這種方式實作單執行個體,有兩個弊端:

  1. 隻有MyClass.get_instance()這樣子執行個體化對象才能實作單執行個體,如果是使用MyClass()這種方式執行個體化,則不能實作單執行個體
  2. 多線程的時候,很可能會出現多個執行個體,因為當調用這個類方法的時候get_instance(),如果在執行個體化過程中__init__函數消耗很長時間,那麼其他的線程的執行個體化,就會認為自己是第一個執行個體化,這樣以來,就會導緻出現多個執行個體

#3.5 重寫__new__方法(推薦)

class MyClass(object):

    def foo(self):

        return None

    def __new__(cls, *args, **kwargs):
        if not hasattr(cls, '_instance'):
            cls._instance = super().__new__(cls)

        return cls._instance


obj1 = MyClass()
obj2 = MyClass()
print(obj1 is obj2)
print(id(obj1))
print(id(obj2))           

複制

Python單執行個體模式

一個對象的執行個體化過程是先執行類的__new__方法,如果我們沒有寫,預設會調用object的__new__方法,傳回一個執行個體化對象,然後再調用__init__方法,對這個對象進行初始化,我們可以根據這個實作單例