0

0

Python单例模式怎么写_基于new方法实现单例数据结构唯一性

P粉602998670

P粉602998670

发布时间:2026-03-18 09:43:44

|

347人浏览过

|

来源于php中文网

原创

__new__ 是实现单例最稳妥的入口,因其在实例化最前端调用、早于 __init__,能真正控制是否创建新对象;需用类变量缓存实例、显式调用父类 __new__,并用 hasattr 防止重复初始化,多线程下需加锁。

python单例模式怎么写_基于new方法实现单例数据结构唯一性

为什么 __new__ 是实现单例最稳妥的入口

因为 __new__ 在对象实例化最前端就被调用,早于 __init__,能真正控制“是否创建新对象”。如果在 __init__ 里做判断,实例其实已经生成了,只是重复初始化——这不叫单例,叫“多次重置”。

  • __new__ 返回的是类实例,你可以在里面拦截并返回已存在的实例
  • 必须显式调用父类的 __new__(即 super().__new__(cls)),否则会报 TypeError: object() takes no arguments
  • 不能在 __new__ 里调用 self.xxx = ...,此时 self 还没完成构造,属性赋值应留给 __init__

标准写法:带类变量缓存的 __new__ 实现

核心是用一个类变量(如 _instance)保存唯一实例,在 __new__ 中检查它是否存在。注意:这个变量必须定义在类体层级,不是方法内局部变量。

class Config:
    _instance = None
<pre class="brush:php;toolbar:false;">def __new__(cls):
    if cls._instance is None:
        cls._instance = super().__new__(cls)
    return cls._instance

def __init__(self):
    # 避免每次调用都重置
    if not hasattr(self, '_inited'):
        self.host = 'localhost'
        self.port = 8000
        self._inited = True

  • 两次 Config() 调用返回同一个对象,id(Config()) == id(Config())True
  • __init__ 里的初始化逻辑用 hasattr(self, '_inited') 守护,防止重复赋值
  • 不加守护的话,每次实例化都会执行 __init__,导致字段被覆盖

多线程下 __new__ 单例会出问题吗

会。标准写法在并发场景中存在竞态条件:cls._instance is None 判断和 super().__new__(cls) 创建之间可能被多个线程同时穿过,导致创建多个实例。

Ai好记
Ai好记

强大的AI音视频转录与总结工具

下载

立即学习Python免费学习笔记(深入)”;

  • 简单修复:用 threading.Lock 包裹实例创建逻辑
  • 更轻量方案:改用模块级单例(Python 模块天然单例),或用装饰器 + functools.lru_cache(maxsize=1)
  • 不要依赖 if not cls._instance:,因为 NoneFalse、空列表等都为假,容易误判;坚持用 is None

为什么不用装饰器或元类?什么情况下必须用 __new__

装饰器(如 @singleton)和元类也能实现单例,但它们作用在类定义层面,而 __new__ 是每个实例化动作的必经关卡——这意味着你能精确控制“哪些调用该走单例,哪些不该”。

  • 需要支持带参数的单例(比如按配置名返回不同单例实例)时,__new__ 可读取 *args**kwargs 做路由
  • 某些 ORM 或框架要求子类必须继承特定基类,且不允许替换类本身(装饰器会换掉原类),这时只能在 __new__ 内部做逻辑
  • 元类写法复杂、调试困难,且对 IDE 类型推导不友好;__new__ 更直观,也更容易单元测试

真正难的不是写出来,而是想清楚:这个单例要不要支持参数化?会不会被继承?有没有并发初始化风险?漏掉任何一个,就不是真单例。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
if什么意思
if什么意思

if的意思是“如果”的条件。它是一个用于引导条件语句的关键词,用于根据特定条件的真假情况来执行不同的代码块。本专题提供if什么意思的相关文章,供大家免费阅读。

848

2023.08.22

if什么意思
if什么意思

if的意思是“如果”的条件。它是一个用于引导条件语句的关键词,用于根据特定条件的真假情况来执行不同的代码块。本专题提供if什么意思的相关文章,供大家免费阅读。

848

2023.08.22

if什么意思
if什么意思

if的意思是“如果”的条件。它是一个用于引导条件语句的关键词,用于根据特定条件的真假情况来执行不同的代码块。本专题提供if什么意思的相关文章,供大家免费阅读。

848

2023.08.22

treenode的用法
treenode的用法

​在计算机编程领域,TreeNode是一种常见的数据结构,通常用于构建树形结构。在不同的编程语言中,TreeNode可能有不同的实现方式和用法,通常用于表示树的节点信息。更多关于treenode相关问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

550

2023.12.01

C++ 高效算法与数据结构
C++ 高效算法与数据结构

本专题讲解 C++ 中常用算法与数据结构的实现与优化,涵盖排序算法(快速排序、归并排序)、查找算法、图算法、动态规划、贪心算法等,并结合实际案例分析如何选择最优算法来提高程序效率。通过深入理解数据结构(链表、树、堆、哈希表等),帮助开发者提升 在复杂应用中的算法设计与性能优化能力。

30

2025.12.22

深入理解算法:高效算法与数据结构专题
深入理解算法:高效算法与数据结构专题

本专题专注于算法与数据结构的核心概念,适合想深入理解并提升编程能力的开发者。专题内容包括常见数据结构的实现与应用,如数组、链表、栈、队列、哈希表、树、图等;以及高效的排序算法、搜索算法、动态规划等经典算法。通过详细的讲解与复杂度分析,帮助开发者不仅能熟练运用这些基础知识,还能在实际编程中优化性能,提高代码的执行效率。本专题适合准备面试的开发者,也适合希望提高算法思维的编程爱好者。

45

2026.01.06

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

806

2023.08.10

Python 多线程与异步编程实战
Python 多线程与异步编程实战

本专题系统讲解 Python 多线程与异步编程的核心概念与实战技巧,包括 threading 模块基础、线程同步机制、GIL 原理、asyncio 异步任务管理、协程与事件循环、任务调度与异常处理。通过实战示例,帮助学习者掌握 如何构建高性能、多任务并发的 Python 应用。

381

2025.12.24

抖漫入口地址合集
抖漫入口地址合集

本专题整合了抖漫入口地址相关合集,阅读专题下面的文章了解更多详细地址。

17

2026.03.17

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 22.5万人学习

Django 教程
Django 教程

共28课时 | 5.1万人学习

SciPy 教程
SciPy 教程

共10课时 | 2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号