最经典的是用__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 模块天然单例——模块只被导入一次,其中定义的对象即全局唯一。无需任何魔法方法或装饰器,简单可靠。
小邮包-包月订购包年服务网,该程序由好买卖商城开发,程序采用PHP+MYSQL架设,程序商业模式为目前最为火爆的包月订制包年服务模式,这种包年订购在国外网站已经热火很多年了,并且已经发展到一定规模,像英国的男士用品网站BlackSocks,一年的袜子购买量更是达到了1000万双。功能:1、实现多产品上线,2、不用注册也可以直接下单购买,3、集成目前主流支付接口,4、下单发货均有邮件提醒。
做法:把类实例直接写在模块文件里,对外暴露该实例即可。适合配置类、工具类、连接池等无参数初始化场景。
例如 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__ 属性。









