【Python進階】Python 單例模式

python 單例模式:

方法一:

py模塊就是天然的單例模式,在其他模塊直接導入實例;

class Singleton:

    def __init__(self):
        pass

    def func(self):
        pass

# 在其他模塊直接導入實例 sln;
sln = Singleton()
# 刪除該類,防止在其他模塊再次實例化
del Singleton

 方法二:

使用裝飾器,該方法實現的單例只會實例化1次,第2次不會再實例化,而是使用已有的實例;
而且可以加入線程鎖,保證線程安全;

from threading import Lock

# 一:先寫個實現單例功能的裝飾器
# 1.實現個裝飾器
def singleton(cls):
    # 2.創建個字段用來存放類的實例
    _instance = {}
    _lock = Lock()

    def wrapper(*args, **kwargs):
        # 線程安全
        with _lock:
            # 3.檢測字典中是否有保存類的實例
            if cls not in _instance.keys():
                # 4.沒有實例便創建實例並保存到字典中
                _instance[cls] = cls(*args, **kwargs)

        return _instance[cls]  # 5.返回實例

    return wrapper  # 6.返回方法


# 二:導入裝飾器,裝飾在類上
@singleton
class ClassDemo:
    def __init__(self, n):
        print(f'參數{n},正在實例化對象...,')


if __name__ == '__main__':

    d1 = ClassDemo(10086)  # 只會實例化1次
    d2 = ClassDemo(10010)  # 第2次不會再次進行實例化,而是引用已有的實例
    print(id(d1))
    print(id(d2))

# 執行結果:=========================
# 參數10086,正在實例化對象...,
# 2364709639728
# 2364709639728

 方法三:

__new__() 方法,此方法第1次實例化時會創建1個新的實例並存儲在類的屬性裏,第2次實例化時不會創建新的實例,而是使用已有的實例,但是會重新爲實例初始化參數,省去創建和銷燬實例的開銷;

from threading import Lock

# Python 在實例化對象的時候類會調用 __new__() 創建一個對象,
# 如果類沒有實現__new__()方法,那麼會調用 Object 的 __new__() 的方法;
# 然後再調用 __init__() 方法進行初始化;

class Singleton_(object):

    def __init__(self, x):
        self.x = x
        print('實例化對象...', x)
    
    # 1.重寫 __new__() 方法
    def __new__(cls, *args, **kwargs):
        # 線程鎖
        _lock = Lock()
        with _lock:
            # 2.檢查是類是否有 _instance 屬性
            if not hasattr(cls, '_instance'):
                # 3.沒有 _instance 屬性便調用父類__new__()方法創建個對象賦值給 _instance 屬性
                cls._instance = super().__new__(cls)
        return cls._instance  # 4. 返回對象實例

if __name__ == '__main__':
    s1 = Singleton_(1)  # 第1次實例化時會創建1個新的實例並存儲再類的屬性裏
    s2 = Singleton_(2)  # 第2次實例化時不會創建新的實例,而是使用已有的實例,但是會重新爲實例初始化參數
    s3 = Singleton_(3)
    s1.func()
    s2.func()
    s3.func()
    print(id(s1))
    print(id(s2))
    print(id(s3))

# 執行結果:============================
# 創建對象...
# 初始化對象... 1
# 不創建對象...
# 初始化對象... 2
# 不創建對象...
# 初始化對象... 3
# 實例屬性: 3
# 實例屬性: 3
# 實例屬性: 3
# 2747330237272
# 2747330237272
# 2747330237272

 

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