单例模式确保一个类仅有一个实例并提供全局访问点,用于日志器、连接池等共享资源;推荐模块级变量实现,天然线程安全;若需类调用则重写__new__并加初始化标志,避免装饰器、懒汉式并发及可变上下文滥用。

什么是单例模式
单例模式确保一个类在整个程序运行期间只有一个实例,并提供全局访问点。它不是为了“炫技”,而是解决实际问题:比如日志记录器、数据库连接池、配置管理器——这些资源通常只需一份,重复创建既浪费又可能引发状态冲突。
最简可靠的实现方式:使用模块级变量
Python 中最自然、最不易出错的单例写法,其实是把类逻辑封装进一个模块,直接暴露实例:
config.py
class Config:
def __init__(self):
self.debug = True
self.host = "localhost"
模块加载时就创建唯一实例
instance = Config()
其他地方直接导入使用:
立即学习“Python免费学习笔记(深入)”;
from config import instance print(instance.debug) # True
这种方式天然线程安全,无需加锁,也绕过了继承、元类等复杂机制,适合绝大多数场景。
需要类接口时:__new__ 控制实例化
如果必须通过 类名() 调用(例如要支持继承或框架集成),重写 __new__ 是清晰可控的选择:
class Logger:
_instance = None
def __new__(cls):
if cls._instance is None:
cls._instance = super().__new__(cls)
cls._instance._initialized = False
return cls._instance
def __init__(self):
if self._initialized:
return
self._log_buffer = []
self._initialized = True
关键点:
- 用 _instance 缓存实例,避免重复调用 __init__
- 引入 _initialized 标志,防止多次初始化内部状态
- 不依赖装饰器或元类,逻辑直白,调试友好
避免常见陷阱
单例容易被误用或写错,注意这几点:
-
别用装饰器“自动”转单例:像
@singleton这类通用装饰器会模糊设计意图,且难以控制初始化时机 -
多线程下慎用懒汉式 + if 判断:纯靠
if _instance is None不保证线程安全,真有并发需求应配合threading.Lock或改用模块单例 - 别在单例里存可变的全局上下文:比如把当前用户 ID 直接塞进单例属性,会导致不同请求互相污染 —— 单例管“资源”,不管“请求状态”










