Python小白学习教程从入门到入坑------第二十六课 单例模式(语法进阶)
在这个节课的开始,我们先回顾一下面向对象课程中学的构造函数__init__()
目录
一、__init__() 和 __new__()
1.1 __init__()
1.2 __new__()
二、单例模式
2.1 特点
2.2 通过@classmethod实现单例模式
2.3 通过装饰器实现单例模式
2.3 通过重写__new__() 实现单例模式
2.4 通过导入模块实现单例模式
三、单例模式的应用场景
一、__init__() 和 __new__()
1.1 __init__()
作用:初始化对象
eg:
class Test(object):def __init__(self):print("这是__init__()")
te = Test()
# 输出结果:这是__init__()
1.2 __new__()
__new__(): object 基类提供的内置的静态方法
作用:
1、在内存中为对象分配空间
2、返回对象的引用
eg:
class Test(object):def __init__(self):print("这是__init__()")def __new__(cls, *args, **kwargs): # cls代表类本身print("我是__new__()")
te = Test()
# 输出结果:我是__new__()
我们会发现,这里面的__init__方法没有输出 ,这是为什么呢?
其实是因为我们在__new__方法中将__new__方法改写了,改变了python中默认__new__的功能,改成了print("我是__new__()"),所以__init__方法没有输出
我们接下来试着打印一下te和cls
eg:没有__new__() 方法时
class Test(object):def __init__(self):print("这是__init__()")
te = Test()
print(te)
# 输出结果:
# 这是__init__()
# <__main__.Test object at 0x000001BF8ABFE148>
加入__new__() 方法时:
class Test(object):def __init__(self):print("这是__init__()")def __new__(cls, *args, **kwargs):print("我是__new__()")print(cls)
te = Test()
print(te)
# 输出结果:
# 我是__new__()
# <class '__main__.Test'>
# None
发现此时te输出为None,就是因为__new__的功能被覆盖改写了
那么我们如果想修改原有的代码,却还想继承原有代码的功能,那么我们该怎么做呢?
我们需要用到之前学习的扩展
eg:
class Test(object):def __init__(self):print("这是__init__()")def __new__(cls, *args, **kwargs):print("我是__new__()")print(cls)# 对父类方法进行扩展 推荐使用super().方法名()res = super().__new__(cls)# 方法重写,res里面保存的是实例对象的引用,__new__()是静态方法,形参里面有cls,实参就必须传clsreturn res# 注意:重写__new__() 一定要return super().__new__(cls),否则python解释器得不到分配空间的对象引用,就不会调用__init__()
te = Test()
print("te:",te)
# 输出结果:
# 我是__new__()
# <class '__main__.Test'>
# 这是__init__()
# te: <__main__.Test object at 0x0000021EBEBEE548>
执行步骤:
一个对象的实例化过程:首先执行__new__(),如果没有写__new__(),默认调用object 里面的__new__(),返回一个实例对象,然后再去调用__init__(),对对象进行初始化
eg:
class Person(object):def __new__(cls, *args, **kwargs):print("这是new方法")print("返回值:",super().__new__(cls))return super().__new__(cls)def __init__(self,name):self.name = name # 实例属性print("名字是:",self.name)
pe = Person('junjun')
print(pe)
pe2 = Person('susu')
print(pe2)
# 输出结果:
# 这是new方法
# 返回值: <__main__.Person object at 0x000002564FA1E5C8>
# 名字是: junjun
# <__main__.Person object at 0x000002564FA1E5C8>
# 这是new方法
# 返回值: <__main__.Person object at 0x000002564FA1E608>
# 名字是: susu
# <__main__.Person object at 0x000002564FA1E608>
总结:__init__() 和 __new__()
1、__new__() 是创建对象,__init__() 是初始化对象
2、__new__() 是返回对象引用,__init__() 定义实例属性
3、__new__() 是类级别的方法,__init__() 是实例级别的方法
二、单例模式
2.1 特点
单例模式(Singleton Pattern)是一种创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点来获取该实例
当你希望在整个系统中,某个类只能出现一个实例时,单例模式就能排上用场(可以简单理解成一个特殊的类,这个类只存在一个对象)
优点:可以节省内存空间,减少了不必要的资源浪费
弊端:多线程访问的时候容易引发线程安全问题
在 Python 中,有多种方式实现单例模式,以下是一些常见的方法:
1、通过@classmethod
2、通过装饰器实现
3、通过重写__new__() 实现(重点)
4、通过导入模块实现
注意:单例模式简单来说就是每一次实例化所创建的对象都是同一个,即内存地址相同
2.2 通过@classmethod实现单例模式
这种方法利用类方法 @classmethod 和一个类变量来追踪单例实例
eg:
class Singleton: _instance = None @classmethod def get_instance(cls, *args, **kwargs): if cls._instance is None: cls._instance = cls(*args, **kwargs) return cls._instance def __init__(self, value=None): if not hasattr(self, 'initialized'): # 防止重复初始化 self.value = value self.initialized = True # 测试
if __name__ == "__main__": s1 = Singleton(10) s2 = Singleton.get_instance(20) # 这里传递的 20 将被忽略,因为实例已经存在 print(s1.value) # 输出: 10 print(s2.value) # 输出: 10,而不是 20 print(s1 is s2) # 输出: True
注意:上面的实现中,__init__ 方法被修改以防止重复初始化。这是因为在第一次创建实例后,后续通过 get_instance 获取实例时不会再次调用 __init__
2.3 通过装饰器实现单例模式
装饰器可以用来将任何类转换为单例
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 @singleton
class Singleton: def __init__(self, value): self.value = value # 测试
if __name__ == "__main__": s1 = Singleton(10) s2 = Singleton(20) # 这里传递的 20 将被忽略,因为实例已经存在(通过装饰器控制) print(s1.value) # 输出: 10 print(s2.value) # 输出: 10 print(s1 is s2) # 输出: True
2.3 通过重写__new__() 实现单例模式
这是最常见和推荐的方法之一,因为它在对象创建的最早阶段就进行控制
设计流程:
1、定义一个类属性,初始值为None,用来记录单例对象的引用
2、重写__new__() 方法
3、进行判断,如果类属性是None,把__new__() 返回的对象引用保存进去
4、返回类属性中记录的对象引用
class Singleton: _instance = None # 类属性def __new__(cls, *args, **kwargs): if cls._instance is None: # 判断类属性是否为空cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs) return cls._instance def __init__(self, value=None): if not hasattr(self, 'initialized'): # 防止重复初始化(同样的问题) self.value = value self.initialized = True # 测试
if __name__ == "__main__": s1 = Singleton(10) s2 = Singleton(20) # 这里传递的 20 将被忽略 print(s1.value) # 输出: 10 print(s2.value) # 输出: 10 print(s1 is s2) # 输出: True
2.4 通过导入模块实现单例模式
Python 模块在第一次导入时会被初始化,并且只会被初始化一次。因此,可以利用这一特性实现单例。
首先,创建一个模块 singleton_module.py:
# singleton_module.py
class Singleton: def __init__(self, value): self.value = value singleton_instance = Singleton(10) # 创建单例实例
然后,在其他文件中使用:
# main.py
import singleton_module # 测试
if __name__ == "__main__": s1 = singleton_module.singleton_instance # 尝试重新赋值不会改变单例实例 # singleton_module.singleton_instance = Singleton(20) # 这行不会影响已经存在的实例 # 但可以通过实例的属性进行修改(如果允许的话) # s1.value = 20 # 这会改变实例的 value 属性 s2 = singleton_module.singleton_instance print(s1.value) # 输出: 10 print(s2 is s1) # 输出: True
注意:在模块级单例中,如果直接修改 singleton_module.singleton_instance 指向另一个对象,那么会破坏单例模式。但是,如果通过实例的属性进行修改(如 s1.value = 20),则不会破坏单例模式,只是改变了实例的状态
三、单例模式的应用场景
1.回收站对象
2.音乐播放器,一个音乐播放软件负责音乐播放的对象只有一个
3.开发游戏软件场景管理器
4.数据库配置、数据库连接池的设计
今天的分享就到这里了,希望本文能够对大家有些许的帮助~
相关文章:
Python小白学习教程从入门到入坑------第二十六课 单例模式(语法进阶)
在这个节课的开始,我们先回顾一下面向对象课程中学的构造函数__init__() 目录 一、__init__() 和 __new__() 1.1 __init__() 1.2 __new__() 二、单例模式 2.1 特点 2.2 通过classmethod实现单例模式 2.3 通过装饰器实现单例模式 2.3 通过重写__new__() 实现…...
革命性AI搜索引擎!ChatGPT最新功能发布,无广告更智能!
文章目录 零、前言一、ChatGPT最新AI搜索引擎功能操作指导实战1:搜索新闻实战2:搜索天气实战3:搜索体育消息 二、感受 零、前言 大人,时代变了。 最强 AI 助力下的无广告搜索引擎终于问世。我们期待已久的这一刻终于到来了,从今天起,ChatGPT…...
windows C#-使用异常
在 C# 中,程序中的运行时错误通过使用一种称为“异常”的机制在程序中传播。 异常由遇到错误的代码引发,由能够更正错误的代码捕捉。 异常可由 .NET 运行时或由程序中的代码引发。 一旦引发了一个异常,此异常会在调用堆栈中传播,直…...
玩的花,云产品也能拼团了!!!
说起拼单大家都不陌生,电商一贯的营销手段,不过确实可以给消费者省下一笔钱。双11到了,腾讯云产品也玩起了拼团,这明显是对开发人员和各企业的福利。 对于有云产品需求的个人或企业,这次绝对是难得的一次薅羊毛机会。…...
HTML+CSS基础【快速上手】
目录 一、HTML展示 1、HTML基础结构 2、认识元素属性 (1)元素属性理解 (2)实例 3、自结束标签和注释 (1)自结束标签 (2)注释 4、语义化标签 (1)语义…...
mysql分布式锁
大家好,今天我们来看下如何使用本地MySql实现一把分布式锁,以及Mysql实现分布式锁的原理是怎么样的 MySql实现分布式锁有三种方式 1:基于行锁实现分布式锁 k1.png 实现原理 首先我们的表lock要提前存好相对应的lockName,这时候…...
探索四款强大的免费报表工具,提升数据可视化能力
概述 在当今数据驱动的时代,报表工具成为了企业分析和可视化数据的重要助手。通过这些工具,用户可以轻松地将原始数据转换为直观易懂的报表,帮助决策者更快地获取信息和做出判断。本文介绍了四款免费的报表工具,包括山海鲸报表、…...
电机可靠性影响因素研究
电机作为现代工业自动化和日常生活中不可或缺的核心设备,其可靠性直接关系到系统的整体性能和安全性。电机的可靠性不仅影响生产效率、降低维护成本,还有助于提高产品的质量和企业的市场竞争力。 一、电机可靠性的概念 电机可靠性是指电机在规定条件下和…...
GB/T 28046.4-2011 道路车辆 电气及电子设备的环境条件和试验 第4部分:气候负荷(6)
写在前面 本系列文章主要讲解道路车辆电气及电子设备的环境条件和试验GB/T 28046标准的相关知识,希望能帮助更多的同学认识和了解GB/T 28046标准。 若有相关问题,欢迎评论沟通,共同进步。(*^▽^*) 第4部分:气候负荷 5. 试验和要求 5.8 流动混合气体腐蚀试验 5.8.1 目的…...
后端接口返回二进制文件,前端 window.opent预览展示
详细步骤 1.修改 PreviewApi 函数: 设置 responseType 为 ‘arraybuffer’,以接收二进制数据。 export const PreviewApi (data) > request({method: post,url: /dev-api/preview,responseType: arraybuffer,data });3.处理响应: 使用…...
基于STM32的红外遥控接收器
1. 引言 红外遥控技术广泛应用于电视、空调等家用电器的控制。通过本项目,我们将学习如何使用STM32开发板搭建一个红外遥控接收器,能够接收来自遥控器的信号,并在串口终端上显示按键信息。 2. 环境准备2.1 硬件需求 - STM32开发板࿰…...
K8S网络插件故障处理
1网络插件故障 1此故障问题处理方法 查询ip是否正常是否是主节点IP地址如果不是需要更改 更改方式 1 修改calico.yaml文件的相应参数 # Cluster type to identify the deployment type - name: IP_AUTODETECTION_METHOD #增加内容value: "interfaceens*" 或者 value…...
优化前端开发中的提示语设计基本原则
文章目录 一致1、同一对象,指称一致2、同一状态,描述一致3、同一行为,提示一致 简洁1、用词简短 条理1、上下呼应2、主次分明 亲和1、化“难”为易2、“礼”字当先3、正向表达 灵动1、用词多变2、远离平淡 契合1、身份契合2、产品契合 示例1、…...
飞凌嵌入式FET527N-C核心板现已适配Android 13
飞凌嵌入式FET527N-C核心板现已成功适配Android13,新系统的支持能够为用户提供更优质的使用体验。那么,运行Android13系统的FET527N-C核心板具有哪些突出的优势呢? 1、性能与兼容性提升 飞凌嵌入式FET527N-C核心板搭载了全志T527系列高性能处…...
uniapp 如何修改 返回按钮(左上角+物理按钮+侧滑)触发的返回事件
背景: 使用uniapp 开发安卓app,在用户编辑后直接返回时,使用弹窗提醒用户:还没有保存,是否保存? 方案 1. 使用自定义返回事件 //返回 back() { // 业务逻辑,弹窗提醒 uni.showModal({title:…...
appium启动 install driver安装驱动
appium启动 appiumPS C:\Windows\system32> appium [Appium] Welcome to Appium v2.12.1 [Appium] The autodetected Appium home path: C:\Users\liyd\.appium [HTTP] Could not start REST http interface listener. The requested port may already be in use. Please m…...
【机器学习】均方误差根(RMSE:Root Mean Squared Error)
均方误差根(Root Mean Squared Error,RMSE)是机器学习和统计学中常用的误差度量指标,用于评估预测值与真实值之间的差异。它通常用于回归模型的评价,以衡量模型的预测精度。 RMSE的定义与公式 给定预测值 和实际值 …...
[含文档+PPT+源码等]精品基于springboot实现的原生Andriod广告播放系统
基于Spring Boot实现的原生Android广告播放系统背景,主要可以从以下几个方面进行阐述: 一、市场需求与背景 移动互联网的快速发展: 随着移动互联网技术的不断进步,智能手机已成为人们日常生活中不可或缺的一部分。人们越来越多地…...
【机器学习】均方误差(MSE:Mean Squared Error)
均方误差(Mean Squared Error, MSE)是衡量预测值与真实值之间差异的一种方法。在统计学和机器学习中,MSE 是一种常见的损失函数,用于评估模型的预测准确性。 均方误差的定义 假设有一组真实值 和模型预测的对应值 。均方误…...
融合虚拟与现实,AR Engine为用户提供沉浸式交互体验
当今的应用市场中,传统的应用产品已经难以完全满足消费者的多样化需求。为了在竞争激烈的市场中脱颖而出,企业需要深入洞察用户需求,提供个性化的服务体验和差异化的产品创新,以吸引并留住消费者。 比如,购物类App通过…...
保姆级教程:用Python+NumPy复现经典Laplacian曲面编辑算法(附源码)
从理论到代码:Python实现Laplacian曲面编辑的完整指南 在三维图形处理领域,Laplacian曲面编辑技术因其出色的细节保持能力而备受推崇。这项技术允许开发者对三维模型进行直观的变形操作,同时保持模型表面的几何细节不被破坏。本文将带您从零开…...
高效浏览器视频嗅探工具:猫抓扩展完整使用指南
高效浏览器视频嗅探工具:猫抓扩展完整使用指南 【免费下载链接】cat-catch 猫抓 浏览器资源嗅探扩展 / cat-catch Browser Resource Sniffing Extension 项目地址: https://gitcode.com/GitHub_Trending/ca/cat-catch 猫抓(Cat-Catch)…...
Applite:macOS软件管理的最佳图形化方案,告别繁琐命令行
Applite:macOS软件管理的最佳图形化方案,告别繁琐命令行 【免费下载链接】Applite User-friendly GUI macOS application for Homebrew Casks 项目地址: https://gitcode.com/gh_mirrors/ap/Applite 还在为macOS软件安装更新而烦恼吗?…...
3分钟完成30分钟任务:词达人自动化助手终极指南
3分钟完成30分钟任务:词达人自动化助手终极指南 【免费下载链接】cdr 微信词达人,高正确率,高效简洁。支持班级任务及自选任务 项目地址: https://gitcode.com/gh_mirrors/cd/cdr 你是否厌倦了每周在词达人平台上花费数小时完成枯燥的…...
基于RAG与向量数据库的智能信息管理系统(IIMS)架构与实现
1. 项目概述:当AI成为你的“第二大脑”最近在折腾一个挺有意思的项目,叫“IIMS-By-AI”。乍一看这个标题,可能有点摸不着头脑,但拆解一下就能明白它的野心:IntelligentInformationManagementSystem, By AI。…...
AI智能体开发实战:从Devin现象到代码辅助智能体构建
1. 项目概述:当开发者遇上AI智能体最近在GitHub上闲逛,发现一个叫“awesome-devins”的仓库热度飙升。点进去一看,好家伙,这简直是一个关于“AI智能体”的宝藏目录。这个由e2b-dev团队维护的项目,本质上是一个精心整理…...
2026运营经理学习数据分析对职场能力提升的影响
一、数据分析在运营管理中的核心价值数据分析能力帮助运营经理优化决策流程,通过数据驱动的方法提升业务效率。掌握用户行为分析、市场趋势预测等技能,能够更精准地制定运营策略。数据可视化工具(如Tableau、Power BI)的应用&…...
告别闪烁屏!瑞芯微RK3399开发板Debian系统烧写保姆级教程(含DriverAssistant v5.1.1 + AndroidTool v2.69)
RK3399开发板Debian系统烧写实战:从屏幕闪烁到完美显示的终极解决方案 当你在RK3399开发板上成功烧写Debian系统后,最期待的莫过于看到系统稳定运行的画面。然而,不少开发者却遭遇了屏幕闪烁的困扰——这个问题看似简单,背后却隐藏…...
Linux系统调用观察与strace实战
Linux系统调用观察与strace实战很多 Linux 问题只靠日志和进程状态很难看清,尤其是在进程存在但无响应、命令卡住不动、文件访问异常或网络连接莫名失败时。此时,观察进程正在进行哪些系统调用,往往能快速揭示它卡在什么地方。中级阶段必须掌…...
MCP2221+Blinka+Jupyter:桌面Python直连I2C传感器实时可视化
1. 项目概述:当桌面电脑“学会”与传感器对话作为一名在嵌入式开发和数据可视化领域摸爬滚打了十多年的老手,我见过太多为了读取一个温度传感器的数据,而不得不先折腾Arduino固件、再折腾串口通信、最后还要自己写个上位机软件的复杂流程。整…...
