Python 实现单例模式多种方法

1次阅读

最经典的是用__new__实现单例:重写__new__,类变量缓存实例,首次调用super().__new__(cls)创建,后续直接返回;装饰器方式解耦逻辑,字典缓存按类键存储;模块级全局变量最简,导入即唯一;元类通过__call__控制实例化。

Python 实现单例模式多种方法

使用 __new__ 方法实现单例

这是最经典、最推荐的 python 单例实现方式。核心在于重写类的 __new__ 方法,在实例创建前控制仅返回同一个对象

关键点:用类变量缓存唯一实例,首次调用时创建,后续直接返回;注意调用父类 super().__new__(cls) 创建对象,不能直接用 cls() 否则会无限递归

示例代码:

class Singleton:     _instance = None <pre class='brush:python;toolbar:false;'>def __new__(cls):     if cls._instance is None:         cls._instance = super().__new__(cls)     return cls._instance

测试

a = Singleton() b = Singleton() print(a is b) # True

使用装饰器封装单例逻辑

把单例行为从类定义中解耦出来,复用性高。装饰器维护一个字典,按类对象为键缓存其实例。

立即学习Python免费学习笔记(深入)”;

优点是不侵入原类定义,适合已有类快速改造;缺点是无法对继承链做统一控制(子类会获得独立实例,除非显式处理)。

常见写法:

def singleton(cls):     instances = {}     def get_instance(*args, **kwargs):         if cls not in instances:             instances[cls] = cls(*args, **kwargs)         return instances[cls]     return get_instance <p>@singleton class Database: def <strong>init</strong>(self): self.connection = "connected"</p><p>db1 = Database() db2 = Database() print(db1 is db2)  # True</p>

使用模块级全局变量(最简方式)

Python 模块天然单例——模块只被导入一次,其中定义的对象即全局唯一。无需任何魔法方法或装饰器,简单可靠。

做法:把类实例直接写在模块文件里,对外暴露该实例即可。适合配置类、工具类、连接池等无参数初始化场景。

例如 config.py

class Config:     def __init__(self):         self.debug = True         self.host = "localhost" <p>config = Config()  # 模块加载时就创建好</p>

其他模块只需 from config import config,拿到的就是同一对象。

使用元类控制实例生成

元类是更底层的控制方式,在类创建阶段就介入。适用于需要统一管理多个单例类、或需在类定义时注入单例行为的复杂场景。

元类重写 __call__(即类被调用实例化时触发),检查是否已存在实例,有则返回,否则新建。

示例:

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] <p>class Logger(metaclass=SingletonMeta): def <strong>init</strong>(self): self.level = "INFO"</p><p>log1 = Logger() log2 = Logger() print(log1 is log2)  # True</p>

注意:Python 3 中必须用 metaclass= 关键字参数指定元类,不是 __metaclass__ 属性。

text=ZqhQzanResources