Python 单例模式(Singleton)知识点汇总
·
Python 单例模式(Singleton)知识点汇总
一、单例模式核心概念
1. 定义
单例模式是一种创建型设计模式,保证一个类在整个程序中只能创建唯一的一个实例,无论实例化多少次,都返回同一个对象。
2. 核心特点
- 类只能有一个实例
- 全局共享同一个对象,节省内存资源
- 适用于:日志工具、数据库连接、配置管理、线程池等场景
3. 使用场景
- 全局配置类(整个程序共用一套配置)
- 数据库连接池(避免重复创建连接)
- 日志记录器(统一写入日志文件)
- 打印机/硬件控制(避免多对象冲突)
二、Python 实现单例的 5 种常用方法
方法1:使用 __new__ 方法(最常用、推荐)
利用 Python 实例化时先调用 __new__ 创建对象,再调用 __init__ 初始化的特性,控制实例创建。
class Singleton:
# 存储唯一实例
_instance = None
def __new__(cls, *args, **kwargs):
# 第一次创建才分配内存
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
# 测试
s1 = Singleton()
s2 = Singleton()
print(s1 is s2) # True,同一个对象
方法2:使用装饰器(简洁优雅)
用装饰器包装类,自动实现单例,不侵入类内部代码。
def singleton(cls):
_instance = {}
def wrapper(*args, **kwargs):
if cls not in _instance:
_instance[cls] = cls(*args, **kwargs)
return _instance[cls]
return wrapper
@singleton
class Test:
pass
t1 = Test()
t2 = Test()
print(t1 is t2) # True
方法3:使用模块(Python 天然单例)
Python 模块本身就是单例,模块只会被加载一次,全局共用。
- 创建
config.py
class Config:
pass
# 创建唯一实例
config = Config()
- 使用
from config import config
方法4:使用类方法(手动控制)
自定义获取实例的方法,禁止直接实例化。
class Singleton:
_instance = None
@classmethod
def get_instance(cls):
if cls._instance is None:
cls._instance = cls()
return cls._instance
# 只能用这个方法获取实例
s1 = Singleton.get_instance()
s2 = Singleton.get_instance()
方法5:使用元类 metaclass(高级)
通过元类控制类的创建行为,底层实现单例。
class SingletonMeta(type):
_instance = None
def __call__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = super().__call__(*args, **kwargs)
return cls._instance
class Test(metaclass=SingletonMeta):
pass
三、带初始化参数的单例(解决 __init__ 重复执行)
默认 __new__ 单例会重复执行 __init__,用以下方式修复:
class Singleton:
_instance = None
_initialized = False # 标记是否初始化过
def __new__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
def __init__(self, name):
# 只初始化一次
if not self._initialized:
self.name = name
self._initialized = True
# 测试
s1 = Singleton("张三")
s2 = Singleton("李四")
print(s1.name) # 张三(不会被覆盖)
print(s1 is s2) # True
四、线程安全的单例(多线程必备)
以上方法在多线程下不安全,可能创建多个实例,需加锁:
import threading
class ThreadSingleton:
_instance = None
_lock = threading.Lock() # 线程锁
def __new__(cls, *args, **kwargs):
# 加锁保证同一时间只有一个线程创建实例
with cls._lock:
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
五、单例模式优缺点
✅ 优点
- 内存中只有一个对象,节省内存
- 避免频繁创建/销毁对象,提升性能
- 全局统一访问,方便管理共享资源
❌ 缺点
- 扩展困难,违背开闭原则
- 单例职责过多,违背单一职责原则
- 单元测试困难(无法 mock 独立对象)
六、Python 单例使用总结
- 首选
__new__方法:简单通用,适合大多数场景 - 简洁用装饰器:代码优雅,不修改类结构
- 极简用模块:Python 天然支持,零代码实现
- 多线程必须加锁:保证线程安全
- 带参数必须控制初始化:避免
__init__重复执行
七、最佳实践代码
# 通用、线程安全、带参数、只初始化一次的单例
import threading
class Singleton:
_instance = None
_lock = threading.Lock()
_initialized = False
def __new__(cls, *args, **kwargs):
with cls._lock:
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
def __init__(self, *args, **kwargs):
if not self._initialized:
# 初始化代码写这里
self.config = args
self._initialized = True
# 使用
if __name__ == '__main__':
a = Singleton("test")
b = Singleton("dev")
print(a is b) # True
总结
- 单例 = 一个类永远只有一个对象
- Python 最常用:
__new__实现、装饰器、模块 - 多线程必须加线程锁
- 带参数单例要防止
__init__重复初始化 - 适合全局唯一资源:配置、数据库连接、日志
更多推荐



所有评论(0)