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

使用 __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__ 属性。