当前位置: 首页 > news >正文

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小白学习教程从入门到入坑------第二十六课 单例模式(语法进阶)

在这个节课的开始&#xff0c;我们先回顾一下面向对象课程中学的构造函数__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:搜索体育消息 二、感受 零、前言 大人&#xff0c;时代变了。 最强 AI 助力下的无广告搜索引擎终于问世。我们期待已久的这一刻终于到来了&#xff0c;从今天起&#xff0c;ChatGPT…...

windows C#-使用异常

在 C# 中&#xff0c;程序中的运行时错误通过使用一种称为“异常”的机制在程序中传播。 异常由遇到错误的代码引发&#xff0c;由能够更正错误的代码捕捉。 异常可由 .NET 运行时或由程序中的代码引发。 一旦引发了一个异常&#xff0c;此异常会在调用堆栈中传播&#xff0c;直…...

玩的花,云产品也能拼团了!!!

说起拼单大家都不陌生&#xff0c;电商一贯的营销手段&#xff0c;不过确实可以给消费者省下一笔钱。双11到了&#xff0c;腾讯云产品也玩起了拼团&#xff0c;这明显是对开发人员和各企业的福利。 对于有云产品需求的个人或企业&#xff0c;这次绝对是难得的一次薅羊毛机会。…...

HTML+CSS基础【快速上手】

目录 一、HTML展示 1、HTML基础结构 2、认识元素属性 &#xff08;1&#xff09;元素属性理解 &#xff08;2&#xff09;实例 3、自结束标签和注释 &#xff08;1&#xff09;自结束标签 &#xff08;2&#xff09;注释 4、语义化标签 &#xff08;1&#xff09;语义…...

mysql分布式锁

大家好&#xff0c;今天我们来看下如何使用本地MySql实现一把分布式锁&#xff0c;以及Mysql实现分布式锁的原理是怎么样的 MySql实现分布式锁有三种方式 1&#xff1a;基于行锁实现分布式锁 k1.png 实现原理 首先我们的表lock要提前存好相对应的lockName&#xff0c;这时候…...

探索四款强大的免费报表工具,提升数据可视化能力

概述 在当今数据驱动的时代&#xff0c;报表工具成为了企业分析和可视化数据的重要助手。通过这些工具&#xff0c;用户可以轻松地将原始数据转换为直观易懂的报表&#xff0c;帮助决策者更快地获取信息和做出判断。本文介绍了四款免费的报表工具&#xff0c;包括山海鲸报表、…...

电机可靠性影响因素研究

电机作为现代工业自动化和日常生活中不可或缺的核心设备&#xff0c;其可靠性直接关系到系统的整体性能和安全性。电机的可靠性不仅影响生产效率、降低维护成本&#xff0c;还有助于提高产品的质量和企业的市场竞争力。 一、电机可靠性的概念 电机可靠性是指电机在规定条件下和…...

GB/T 28046.4-2011 道路车辆 电气及电子设备的环境条件和试验 第4部分:气候负荷(6)

写在前面 本系列文章主要讲解道路车辆电气及电子设备的环境条件和试验GB/T 28046标准的相关知识,希望能帮助更多的同学认识和了解GB/T 28046标准。 若有相关问题,欢迎评论沟通,共同进步。(*^▽^*) 第4部分:气候负荷 5. 试验和要求 5.8 流动混合气体腐蚀试验 5.8.1 目的…...

后端接口返回二进制文件,前端 window.opent预览展示

详细步骤 1.修改 PreviewApi 函数&#xff1a; 设置 responseType 为 ‘arraybuffer’&#xff0c;以接收二进制数据。 export const PreviewApi (data) > request({method: post,url: /dev-api/preview,responseType: arraybuffer,data });3.处理响应&#xff1a; 使用…...

基于STM32的红外遥控接收器

1. 引言 红外遥控技术广泛应用于电视、空调等家用电器的控制。通过本项目&#xff0c;我们将学习如何使用STM32开发板搭建一个红外遥控接收器&#xff0c;能够接收来自遥控器的信号&#xff0c;并在串口终端上显示按键信息。 2. 环境准备2.1 硬件需求 - STM32开发板&#xff0…...

K8S网络插件故障处理

1网络插件故障 1此故障问题处理方法 查询ip是否正常是否是主节点IP地址如果不是需要更改 更改方式 1 修改calico.yaml文件的相应参数 # Cluster type to identify the deployment type - name: IP_AUTODETECTION_METHOD #增加内容value: "interfaceens*" 或者 value…...

优化前端开发中的提示语设计基本原则

文章目录 一致1、同一对象&#xff0c;指称一致2、同一状态&#xff0c;描述一致3、同一行为&#xff0c;提示一致 简洁1、用词简短 条理1、上下呼应2、主次分明 亲和1、化“难”为易2、“礼”字当先3、正向表达 灵动1、用词多变2、远离平淡 契合1、身份契合2、产品契合 示例1、…...

飞凌嵌入式FET527N-C核心板现已适配Android 13

飞凌嵌入式FET527N-C核心板现已成功适配Android13&#xff0c;新系统的支持能够为用户提供更优质的使用体验。那么&#xff0c;运行Android13系统的FET527N-C核心板具有哪些突出的优势呢&#xff1f; 1、性能与兼容性提升 飞凌嵌入式FET527N-C核心板搭载了全志T527系列高性能处…...

uniapp 如何修改 返回按钮(左上角+物理按钮+侧滑)触发的返回事件

背景&#xff1a; 使用uniapp 开发安卓app&#xff0c;在用户编辑后直接返回时&#xff0c;使用弹窗提醒用户&#xff1a;还没有保存&#xff0c;是否保存&#xff1f; 方案 1. 使用自定义返回事件 //返回 back() { // 业务逻辑&#xff0c;弹窗提醒 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)

均方误差根&#xff08;Root Mean Squared Error&#xff0c;RMSE&#xff09;是机器学习和统计学中常用的误差度量指标&#xff0c;用于评估预测值与真实值之间的差异。它通常用于回归模型的评价&#xff0c;以衡量模型的预测精度。 RMSE的定义与公式 给定预测值 和实际值 …...

[含文档+PPT+源码等]精品基于springboot实现的原生Andriod广告播放系统

基于Spring Boot实现的原生Android广告播放系统背景&#xff0c;主要可以从以下几个方面进行阐述&#xff1a; 一、市场需求与背景 移动互联网的快速发展&#xff1a; 随着移动互联网技术的不断进步&#xff0c;智能手机已成为人们日常生活中不可或缺的一部分。人们越来越多地…...

【机器学习】均方误差(MSE:Mean Squared Error)

均方误差&#xff08;Mean Squared Error, MSE&#xff09;是衡量预测值与真实值之间差异的一种方法。在统计学和机器学习中&#xff0c;MSE 是一种常见的损失函数&#xff0c;用于评估模型的预测准确性。 均方误差的定义 假设有一组真实值 ​ 和模型预测的对应值 ​。均方误…...

融合虚拟与现实,AR Engine为用户提供沉浸式交互体验

当今的应用市场中&#xff0c;传统的应用产品已经难以完全满足消费者的多样化需求。为了在竞争激烈的市场中脱颖而出&#xff0c;企业需要深入洞察用户需求&#xff0c;提供个性化的服务体验和差异化的产品创新&#xff0c;以吸引并留住消费者。 比如&#xff0c;购物类App通过…...

后进先出(LIFO)详解

LIFO 是 Last In, First Out 的缩写&#xff0c;中文译为后进先出。这是一种数据结构的工作原则&#xff0c;类似于一摞盘子或一叠书本&#xff1a; 最后放进去的元素最先出来 -想象往筒状容器里放盘子&#xff1a; &#xff08;1&#xff09;你放进的最后一个盘子&#xff08…...

React第五十七节 Router中RouterProvider使用详解及注意事项

前言 在 React Router v6.4 中&#xff0c;RouterProvider 是一个核心组件&#xff0c;用于提供基于数据路由&#xff08;data routers&#xff09;的新型路由方案。 它替代了传统的 <BrowserRouter>&#xff0c;支持更强大的数据加载和操作功能&#xff08;如 loader 和…...

FFmpeg 低延迟同屏方案

引言 在实时互动需求激增的当下&#xff0c;无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作&#xff0c;还是游戏直播的画面实时传输&#xff0c;低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架&#xff0c;凭借其灵活的编解码、数据…...

STM32F4基本定时器使用和原理详解

STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...

在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module

1、为什么要修改 CONNECT 报文&#xff1f; 多租户隔离&#xff1a;自动为接入设备追加租户前缀&#xff0c;后端按 ClientID 拆分队列。零代码鉴权&#xff1a;将入站用户名替换为 OAuth Access-Token&#xff0c;后端 Broker 统一校验。灰度发布&#xff1a;根据 IP/地理位写…...

高等数学(下)题型笔记(八)空间解析几何与向量代数

目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...

浅谈不同二分算法的查找情况

二分算法原理比较简单&#xff0c;但是实际的算法模板却有很多&#xff0c;这一切都源于二分查找问题中的复杂情况和二分算法的边界处理&#xff0c;以下是博主对一些二分算法查找的情况分析。 需要说明的是&#xff0c;以下二分算法都是基于有序序列为升序有序的情况&#xf…...

Springboot社区养老保险系统小程序

一、前言 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;社区养老保险系统小程序被用户普遍使用&#xff0c;为方…...

Windows安装Miniconda

一、下载 https://www.anaconda.com/download/success 二、安装 三、配置镜像源 Anaconda/Miniconda pip 配置清华镜像源_anaconda配置清华源-CSDN博客 四、常用操作命令 Anaconda/Miniconda 基本操作命令_miniconda创建环境命令-CSDN博客...

从 GreenPlum 到镜舟数据库:杭银消费金融湖仓一体转型实践

作者&#xff1a;吴岐诗&#xff0c;杭银消费金融大数据应用开发工程师 本文整理自杭银消费金融大数据应用开发工程师在StarRocks Summit Asia 2024的分享 引言&#xff1a;融合数据湖与数仓的创新之路 在数字金融时代&#xff0c;数据已成为金融机构的核心竞争力。杭银消费金…...