Python单例模式详解:从原理到实战的完整指南

引言

单例模式是软件设计中最常用的模式之一,它确保一个类只有一个实例,并提供全局访问点。在Python中,实现单例模式有多种优雅的方式,本文将详细讲解6种主流实现方法,包含完整代码示例和注释。

一、模块级单例(最简单实现)

原理:Python模块天然具有单例特性,因为模块只会被导入一次。

# singleton_module.py
class Singleton:def __init__(self):self.data = "Module-level Singleton"# 全局唯一实例
singleton_instance = Singleton()
# main.py
from singleton_module import singleton_instanceprint(singleton_instance.data)  # 输出: Module-level Singleton

优点

  • 无需额外代码,天然支持单例
  • 简单直接,适合简单场景

缺点

  • 实例在模块导入时即创建,无法懒加载
  • 灵活性较差

二、__new__方法实现(经典方式)

原理:通过重写__new__方法控制实例创建过程

class Singleton:_instance = Nonedef __new__(cls, *args, **kwargs):if not cls._instance:cls._instance = super().__new__(cls)cls._instance._initialized = Falsereturn cls._instancedef __init__(self):if self._initialized:returnself._initialized = Trueself.data = "Initialized once"s1 = Singleton()
s2 = Singleton()
print(s1 is s2)  # True

关键点

  • 使用类属性_instance存储唯一实例
  • __init__方法通过标志位防止重复初始化

三、装饰器实现(最灵活方式)

原理:使用装饰器缓存类实例

from functools import wrapsdef singleton(cls):instances = {}@wraps(cls)def wrapper(*args, **kwargs):if cls not in instances:instances[cls] = cls(*args, **kwargs)return instances[cls]return wrapper@singleton
class Database:def __init__(self):print("Database created")db1 = Database()  # 输出: Database created
db2 = Database()  # 无输出
print(db1 is db2)  # True

优势

  • 可复用,适用于任何类
  • 代码与业务逻辑分离

四、元类实现(最Pythonic方式)

原理:通过自定义元类控制类创建过程

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]class Logger(metaclass=SingletonMeta):def __init__(self):self.messages = []log1 = Logger()
log2 = Logger()
print(log1 is log2)  # True

特点

  • 自动处理继承关系
  • 线程安全(Python3特性)

五、线程安全版本(多线程环境)

import threadingdef singleton(cls):instances = {}lock = threading.Lock()@wraps(cls)def wrapper(*args, **kwargs):with lock:if cls not in instances:instances[cls] = cls(*args, **kwargs)return instances[cls]return wrapper

六、惰性初始化(cached_property)

原理:利用Python 3.8+的cached_property特性

from functools import cached_propertyclass AppConfig:@cached_propertydef instance(self):print("Creating config")return {"theme": "dark"}config = AppConfig()
print(config.instance)  # 输出配置并创建实例
print(config.instance)  # 直接返回缓存实例

各种实现方式对比

方法线程安全灵活性复杂度适用场景
模块级单例★☆☆☆☆简单全局对象管理
__new__方法★★☆☆☆★★☆☆☆需要控制实例化过程
装饰器★★★★☆★★☆☆☆多类需要单例时
元类★★★★☆★★★☆☆框架开发/复杂需求
cached_property★★★☆☆★★☆☆☆惰性初始化场景

实际应用场景

  1. 数据库连接池:确保整个应用使用同一个连接池
  2. 日志记录器:统一管理日志输出
  3. 配置管理器:全局共享配置信息
  4. 硬件设备驱动:如打印机、扫描仪等物理设备控制

注意事项

  1. 线程安全:多线程环境下建议使用元类或加锁版本
  2. 序列化问题:元类实现可能影响pickle操作
  3. 继承问题:使用基类实现时需注意多重继承
  4. 测试建议:始终使用is运算符验证单例

总结

  • 简单场景:优先选择模块级单例
  • 多类复用:使用装饰器方案
  • 框架开发:推荐元类实现
  • 惰性加载:使用cached_property

通过本文的6种实现方式,您可以根据具体场景选择最合适的单例模式实现方案。每种方法都包含完整代码和详细注释,方便直接应用到实际项目中。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/915102.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/915102.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

拼团系统中的幂等性防护 , 前置性查询,Redis 库存预判

这段内容涉及两个关键点:幂等性防护 和 拼团目标量判断,下面我将分别解释这两个问题,并重点说明: “如果没有拦截,最终访问数据,也会有数量判断拦截。” 这句话的意思。 ✅ 1. 查询外部交易 outTradeNo 是…

【Python】LEGB作用域 + re模块 + 正则表达式

文章目录一 LEGB作用域二 re(Regular Expression)预览1. re.match() —— 从字符串开头匹配2. re.search() —— 搜索整个字符串3. re.findall() —— 返回所有匹配的字符串列表4. re.finditer() —— 返回所有匹配的迭代器5. re.sub() —— 替换匹配的字…

JavaSE -- 数据操作流

6. 数据操作流在执行文件存储一个对象的时候,如果该对象只有少量属性需要存储,并且这些属性的类型都是基本数据类型,此时则不需要对象序列化技术。使用数据操作流既可以实现。 DataOutputStreamDataInputStream 注意: 读取数据的时…

GI6E 加密GRID電碼通信SHELLCODE載入

GI6E https://github.com/MartinxMax/gi6e 「它似乎能從特製的音訊信號中提取敏感資訊。」 HEX-GRID CODEX(簡稱 HGC)是一種自定義的 6 位元結構編碼系統,使用三位元的群組識別碼(Group Bits)加上三位元的索引識別碼…

实习十三——传输层协议

补充子网划分的主要目的就是为了节约IP,降低成本,但是如果划分私有IP网段,则完全没有意义,因为私有IP可重复,不要钱,所以私有IP严禁进行子网掩码划分传输层协议TCP三次握手TCP协议数据格式第一次握手&#…

RPG59.玩家拾取物品三:可拾取物品的提示UI

1。以WarriorWidgetBase作为父类,创建一个子类的userwidget2.布局为两个值都为1203。然后我们需要想办法,在合适的位置,用bool来控制此控件的显示与隐藏。情况为:当玩家触发与可拾取物体的重叠时,我们将广播一个bool值…

Vue.js 国际化 (i18n) 实践:让你的应用走向全球,多语言支持如此简单!

文章目录一、为何你的 Vue.js 应用需要“说多种语言”?国际化的重要性二、Vue I18n 基础实践:从零开始搭建多语言环境2.1 安装 Vue I18n2.2 配置 Vue I18n 实例2.3 在组件中使用翻译三、进阶实践:让国际化更强大、更灵活3.1 动态语言切换3.2 …

在CentOS7.9服务器上安装.NET 8.0 SDK

在 CentOS 7.9 系统上手动安装 .NET 8.0 SDK(使用本地的 dotnet-sdk-8.0.101-linux-x64.tar.gz 文件),可以按照以下步骤进行操作。由于 CentOS 7.9 已不再被微软官方支持,可能会遇到依赖库版本问题(如 GLIBCXX 和 GLIB…

HarmonyOS-ArkUI Web控件基础铺垫4--TCP协议- 断联-四次挥手解析

HarmonyOS-ArkUI: Web组件加载流程1 HarmonyOS-ArkUI Web控件基础铺垫1-HTTP协议-数据包内容 HarmonyOS-ArkUI Web控件基础铺垫2-DNS解析 HarmonyOS-ArkUI Web控件基础铺垫3--TCP协议- 从规则本质到三次握手-CSDN博客 接上文,上文我们讲解了: 数据在…

如何用AI 生成论文/书籍的摘要

不知道大家是否有这样的感觉,上网浏览信息,看到好的文章就兴奋地下载了下来,文件的名称通常是一串奇奇怪怪的字符串。过了几天就在电脑中找不着了。没有网络上搜索不到的文章,而是在你的电脑中却找不到它们。几年下来,…

ubuntu系统+N卡 | docker compose+ollama+dify(dify和ollama在同一容器)

1、安装NVIDIA驱动 2、安装docker,docker compose 3、安装NVIDIA Container Toolkit Installing the NVIDIA Container Toolkit — NVIDIA Container Toolkit(仅 GPU 场景需要) # Configure the production repository: curl -fsSL https://…

实习手记:基于大模型的搜索引擎开发实践

初入团队:从理论到实践的跨越五月份开始,我怀着忐忑又期待的心情以线上的方式加入了公司AI研发中心的搜索引擎优化小组。作为一名数据科学与大数据技术专业的学生,这是我第一次参与工业级AI项目的开发,团队的任务是构建一个基于大…

用Python实现神经网络(二)

#Overfitting是机器学习的主要问题。下面我们来看一下过拟合现像:import numpy as npimport matplotlib.pyplot as pltimport matplotlib as mplimport tensorflow as tffrom scipy.optimize import curve_fit# Generic matplotlib parameters for plots and figure…

数据结构入门 (二):挣脱连续空间的束缚 —— 单向链表详解

TOC(目录) 引言:整齐的代价 在上一篇文章中,我们一起探索了数据结构大家族的第一位成员——顺序表。我们了解到,顺序表作为一种线性结构,其最大的特点在于逻辑顺序与物理顺序的一致性,即元素之间不仅存在逻辑上的前后关…

AI-视频一致性与多帧控制在AIGC中的技术挑战与突破!

全文目录:开篇语前言1. 视频中人物一致性建模的难点与现有解决方案**人物一致性建模的挑战****现有解决方案****案例代码:基于姿态估计的多帧一致性保持**2. 光照/纹理/姿态跨帧保持方法剖析**跨帧光照与纹理一致性****跨帧姿态一致性**3. 帧间插值与关键…

基于Qwen2.5-3B-Instruct的LoRA微调与推理实战指南

前言 大语言模型(LLM)的微调是当前AI领域的热门话题,而参数高效微调方法(如LoRA)因其低成本和高效率备受关注。本文将手把手教你如何使用Qwen2.5-3B-Instruct模型进行LoRA微调,并构建完整的推理流程。 一、环境准备 1.1 硬件要求 • GPU: 至少16GB显存(如…

电脑插上u盘不显示怎么回事

对于经常使用电脑的用户来说,U盘是一种再熟悉不过的存储工具。不管是拷贝资料、备份文件,还是制作启动盘,U盘都发挥着重要作用。然而,有时候你可能会遇到这样的情况:“U盘插上电脑,灯亮了,但电脑…

2025年6月GESP(C++二级): 幂和数

2025年6月GESP(C++二级): 幂和数 题目描述 对于正整数 n n n,如果 n n n 可以表为两个

Windows、macOS、liunx下使用qemu搭建riscv64/linux

背景 在Windows、macOS和Linux环境下使用QEMU搭建RISC-V 64位Linux系统,网络上存在大量过时、不完整或错误的教程。且部分AI生成的内容“幻觉”现象严重,导致关键步骤错误且难以进行。为确保可靠性,本教程基于最新实测验证,涵盖三…

简单使用MCP

1、说明# 测试环境服务器 CPU数量:2核 内存:4GB 磁盘:50GB# 补充 如果不想使用Docker进行操作,只需要跳过Docker相关命令操作 即:使用Ollama运行模型,使用Python来创建MCP2、安装Docker# 安装Docker https:…