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