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))

20200221145958-image.png

在類前加個裝飾器,在這裏裝飾器的目的只有一個,就是在類實例化前,先判斷這個類有沒有實例化過,如果沒有,則實例化,如果實例化過,測返回之前的實例化對象

#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))

20200222145424-image.png

以這種方式實現單實例,有兩個弊端:

  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))

20200222155934-image.png

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章