在 Python 里,單例模式指的是一個類僅有一個實例,并且提供一個全局訪問點來獲取該實例。下面為你介紹幾種實現單例模式的常見方法。
1. 使用模塊
在 Python 里,模塊天然就是單例模式。當模塊被導入時,Python 會對其進行一次加載和執行,之后再導入相同模塊時,會直接使用之前已經加載的模塊對象。
# singleton.py
class Singleton:def __init__(self):self.value = Nonedef set_value(self, value):self.value = valuedef get_value(self):return self.valuesingleton_instance = Singleton()
在其他文件中使用該單例:
# main.py
from singleton import singleton_instancesingleton_instance.set_value(42)
print(singleton_instance.get_value())
這種方式簡單直接,不過它將單例的實例化過程放在了模塊級別,可能會讓代碼的結構和意圖不夠清晰。
2. 使用裝飾器
借助裝飾器可以把一個類變成單例模式,以下是實現代碼:
def singleton(cls):instances = {}def wrapper(*args, **kwargs):if cls not in instances:instances[cls] = cls(*args, **kwargs)return instances[cls]return wrapper@singleton
class MySingleton:def __init__(self):pass# 使用單例類
s1 = MySingleton()
s2 = MySingleton()
print(s1 is s2)
在上述代碼中,singleton
裝飾器內部維護了一個字典 instances
,用于存儲每個類的單例實例。當調用被裝飾的類來創建實例時,會先檢查該類是否已經有實例存在,如果沒有則創建一個新實例并存儲在字典中,否則直接返回已有的實例。
3. 使用元類
元類是創建類的類,通過自定義元類可以實現單例模式:
class SingletonMeta(type):_instances = {}def __call__(cls, *args, **kwargs):if cls not in cls._instances:cls._instances[cls] = super().__call__(*args, **kwargs)return cls._instances[cls]class MySingleton(metaclass=SingletonMeta):def __init__(self):pass# 使用單例類
s1 = MySingleton()
s2 = MySingleton()
print(s1 is s2)
這里定義了一個元類 SingletonMeta
,在元類的 __call__
方法中實現了單例的邏輯。當使用該元類創建類時,每次實例化該類都會返回同一個實例。
4. 基于 __new__
方法
在類的 __new__
方法中實現單例邏輯:
class MySingleton:_instance = Nonedef __new__(cls, *args, **kwargs):if not cls._instance:cls._instance = super().__new__(cls)return cls._instancedef __init__(self):pass# 使用單例類
s1 = MySingleton()
s2 = MySingleton()
print(s1 is s2)
__new__
方法是在實例創建之前被調用的,在這個方法里檢查類的 _instance
屬性是否已經存在實例,如果不存在則創建一個新實例并賦值給 _instance
,否則直接返回已有的實例。
這些方法各有優劣,你可以根據具體需求來選擇合適的實現方式。