1.業務場景
windows的回收站其實就是一個單例,你雙擊第二次並不會在出現一個出現窗口,對象只會創建一次
第三方sdk做接口發送短信驗證碼,如果有幾十萬個用戶同時發送短信,只需調用對象的方法即可
我們一般在調用數據庫的時候也採用單例模式來實現的,這樣避免了內存空間不必要的佔用和浪費
2.文件導入的形式
模塊在第一次導入時,會生成 .pyc
文件,當第二次導入時,就會直接加載 .pyc
文件,而不會再次執行模塊代碼。
這個其實在django中的admin組件用到過,自己編寫相關組件時候,相當的有用
s1.py class Foo(object): def test(self): print("123") v = Foo() #v是Foo的實例 s2.py from s1 import v as v1 # 第一次導入,實例化並放進內存
s3.py from s1 import v as v2 # 第二次導入直接從內存中獲取
2.基於類實現
2.1 基於__new__方法實現
常見模式1:
class B: __instance = None def __new__(cls, *args, **kwargs): if cls.__instance is None: cls.__instance = object.__new__(cls) return cls.__instance def __init__(self,name,age): self.name = name self.age = age a = B('alex',80) b = B('egon',20) print(a) print(b) print(a.name) print(b.name) # <__main__.B object at 0x04F1D330> # 結果相同 # <__main__.B object at 0x04F1D330> # egon # egon
常見模式2:
class A: def __new__(cls, *args, **kwargs): if not hasattr(cls,'instance'): # 每次實例化,都返回這同一個對象 cls.instance = super().__new__(cls) return cls.instance obj1 = A() obj2 = A() obj1.attr = 'value' print(obj1.attr) print(obj2.attr) # value # value
2.2 與線程相關
不支持多線程:
class Singleton(object): def __init__(self): import time time.sleep(1) @classmethod def instance(cls, *args, **kwargs): if not hasattr(Singleton, "_instance"): Singleton._instance = Singleton(*args, **kwargs) return Singleton._instance import threading def task(arg): obj = Singleton.instance() print(obj) for i in range(10): t = threading.Thread(target=task,args=[i,]) t.start()
支持多線程:
import time import threading class Singleton(object): _instance_lock = threading.Lock() def __init__(self): time.sleep(1) @classmethod def instance(cls, *args, **kwargs): if not hasattr(Singleton, "_instance"): with Singleton._instance_lock: #爲了保證線程安全在內部加鎖 if not hasattr(Singleton, "_instance"): Singleton._instance = Singleton(*args, **kwargs) return Singleton._instance def task(arg): obj = Singleton.instance() print(obj) for i in range(10): t = threading.Thread(target=task,args=[i,]) t.start() time.sleep(20) obj = Singleton.instance() print(obj) # 使用先說明,以後用單例模式,obj = Singleton.instance() # 示例: # obj1 = Singleton.instance() # obj2 = Singleton.instance() # print(obj1,obj2) # 錯誤示例 # obj1 = Singleton() # obj2 = Singleton() # print(obj1,obj2)
3.通過裝飾器實現
def wrapper(cls): instance = {} def inner(*args,**kwargs): if cls not in instance: instance[cls] = cls(*args,**kwargs) return instance[cls] return inner @wrapper class Singleton(object): def __init__(self,name,age): self.name = name self.age = age obj1 = Singleton('尼古拉斯',99) obj2 = Singleton('藍恩',19) print(obj1) print(obj2)