【面试】在Python中如何实现单例模式

点评:单例模式是指让一个类只能创建出唯一的实例,这个题目在面试中出现的频率极高,因为它考察的不仅仅是单例模式,更是对Python语言到底掌握到何种程度,建议大家用装饰器元类这两种方式来实现单例模式,因为这两种方式的通用性最强,而且也可以顺便展示自己对装饰器和元类中两个关键知识点的理解。

方法一: 使用装饰器实现单例模式。

from functools import wraps

def 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 President:

    pass

扩展:装饰器是Python中非常有特色的语法,用一个函数去装饰另一个函数或类,为其添加额外的能力。通常通过装饰来实现的功能都属横切关注功能,也就是跟正常的业务逻辑没有必然联系,可以动态添加或移除的功能。装饰器可以为代码提供缓存、代理、上下文环境等服务,它是对设计模式中代理模式的践行。在写装饰器的时候,带装饰功能的函数(上面代码中的wrapper函数)通常都会用functools模块中的wraps再加以装饰,这个装饰器最重要的作用是给被装饰的类或函数动态添加一个__wrapped__属性,这个属性会将被装饰之前的类或函数保留下来,这样在我们不需要装饰功能的时候,可以通过它来取消装饰器,例如可以使用President = President.__wrapped__来取消对President类做的单例处理。需要提醒大家的是:上面的单例并不是线程安全的,如果要做到线程安

全,需要对创建对象的代码进行加锁的处理。在Python中可以使用threading模块的RLock对象来提供锁,可以使用锁对象的acquire和release方法来实现加锁和解锁的操作。当然,更为简便的做法是使用锁对象的with上下文语法来进行隐式的加锁和解锁操作。

方法二: 使用元类实现单例模式。

class SingletonMeta(type):

    """自定义单例元类"""

    def __init__(cls, *args, **kwargs):

        cls.__instance = None

        super().__init__(*args, **kwargs)

    def __call__(cls, *args, **kwargs):

        if cls.__instance is None:

            cls.__instance = super().__call__(*args, **kwargs)

        return cls.__instance

class President(metaclass=SingletonMeta):

    pass

扩展:Python是面向对象的编程语言,在面向对象的世界中,一切皆为对象。对象是通过类来创建的,而类本身也是对象,类这样的对象是通过元类来创建的。我们在定义类时,如果没有给一个类指定父类,那么默认的父类是object,如果没有给一个类指定元类,那么默认的元类是type。通过自定义的元类,我们可以改变一个类默认的行为,就如同上面的代码中,我们通过元类的__call__魔术方法,改变了President类的构造器那样。

补充:关于单例模式,在面试中还有可能被问到它的应用场景。通常一个对象的状态是被其他对象共享的,就可以将其设计为单例,例如项目中使用的数据库连接池对象和配置对象通常都是单例,这样才能保证所有地方获取到的数据库连接和配置信息是完全一致的;而且由于对象只有唯一的实例,因此从根本上避免了重复创建对象造成的时间和空间上的开销,也避免了对资源的多重占用。

再举个例子,项目中的日志操作通常也会使用单例模式,这是因为共享的日志文件一直处于打开状态,只能有一个实例去操作它,否则在写入日志的时候会产生混乱。

这个我还没完全弄懂,我懂了之后再来补充内容解释

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

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

相关文章

C++输入输出流

C输出流,输入输出是数据的传递过程,数据如流水一般从一处流向另一处,C形象的将此过程称为流。 输入操作:是控制序列中的字节内容从一个设备流入内存 输出操作:是控制序列中的字节内容从内存流向某个设备 目录 1 C输入…

学习笔记 -- TVS管选型参考

一、TVS管基本工作原理 当TVS管(瞬态电压抑制器)两极受到反向瞬态高能量冲击时,能以纳秒(ns)量级的速度,将两极间的高阻抗变为低阻抗,使两极间的电压箝位于一个预定的值,有效地保护电子线路中的元器件。 在浪涌电压作用下&#xf…

ETLCloud详解,如何实现最佳实践及问题排查

ETLCloud介绍 ETLCloud是新一代全域数据集成平台,领先于市场同类产品的数据集成平台(DataOps),只需单击几下即可完成数据清洗转换、传输入仓等操作,具备高效、智能、一站式的全域数据集成优势,如: 毫秒级实时数据同步 …

【华为数据之道学习笔记】4-4传统信息架构向业务数字化扩展:对象、过程、 规则

传统信息架构的缺陷 随着数字化转型的深入,发现既有信息架构已经无法满足自身业务需要,主要体现在以下 几个方面。 1)大量业务和作业所产生的数据并没有完整地被管理 很多情况下,并不是所有业务和作业所产生的数据都在系统中承载…

编程之旅:从电脑故障到创造虚拟世界

创作方向:回顾自己学习编程的过程,分享经历和成长感悟。 当初选择学习计算机,我满怀梦想地说出了成为一名神奇的码农的愿望。我想象着能够像编织魔法一样,通过编写程序创造出炫酷的虚拟世界。然而,我很快就意识到&…

UE虚幻引擎中程序无需运行也可调试

首先先新建一个蓝图类,在蓝图类中创建一个Custom event 事件,然后在右侧细节面板中搜索call in editor,编译保存之后,将该蓝图类拖拽到关卡场景中,在细节面板中即可看到该事件的按钮。

函数指针与指针函数

函数指针: 定义 函数指针是指向函数的指针,其本质是一个指针变量,该指针指向这个函数。即指针存储的地址是一个函数的地址,函数指针就是指向函数的指针。 用途 函数指针可以作为参数传递给其他函数,用于回调函数&am…

跨界电商的科技护航:Socks5代理与代理IP的无限可能

随着全球市场的无缝连接,出海跨界电商成为企业迈向国际舞台的关键一步。然而,面对不同国家和地区的网络环境和限制,科技手段成为企业成功出海的必备利器。本文将深入研究Socks5代理与代理IP在跨界电商中的技术性应用,揭示它们是如…

车载导航系统UI界面,可视化大屏设计(PS源文件)

大屏组件可以让UI设计师的工作更加便捷,使其更高效快速的完成设计任务。现分享车载导航系统科技风蓝黑简约UI界面、车载系统UI主界面、车载系统科技风UI界面、首页车载系统科技感界面界面的大屏Photoshop源文件,开箱即用! 若需 更多行业 相关…

1116 多二了一点

若一个正整数有 2n 个数位,后 n 个数位组成的数恰好比前 n 个数位组成的数多 2,则称这个数字“多二了一点”。如 24、6668、233235 等都是多二了一点的数字。 给定任一正整数,请你判断它有没有多二了那么一点。 输入格式: 输入在…

vxe-table循环生成表格,表格里的某些数值设置颜色

业务需求&#xff1a;表格的列名是循环出来的&#xff0c;后台返回每行的表格数据结构如下&#xff0c;需要表格里只有“当期”的行里数值超限waterGuildLine后显示红色。需要在vxe-table里写个插槽&#xff0c;再写个方法。 <vxe-table border ref"dayTableRef" …

hadoop安装包解压之后的操作

Hadoop解压完成之后配置流程 修改hadoop-env.sh和yarn-env.sh 进入hadoop-3.2.4/etc/hadoop/ 修改这两个文件增加 &#xff1a; JAVA_HOME{java的路径}修改配置文件core-site.xml 和 hdfs-site.xml 进入hadoop-3.2.4/etc/hadoop/ 修改这两个文件增加 &#xff1a; // 这是c…

【MySQL】——数据类型及字符集

&#x1f383;个人专栏&#xff1a; &#x1f42c; 算法设计与分析&#xff1a;算法设计与分析_IT闫的博客-CSDN博客 &#x1f433;Java基础&#xff1a;Java基础_IT闫的博客-CSDN博客 &#x1f40b;c语言&#xff1a;c语言_IT闫的博客-CSDN博客 &#x1f41f;MySQL&#xff1a…

js 原型 和 原型链

function Person(name,age){ this.name name this.age age } var p new Person(张三,11) //创建构造函数的时候&#xff0c;解析器会自动为构造函数创建prototype属性&#xff0c;prototype属性对应的对象就是原型对象 // prototype 翻译为 原…

HI3559AV100和FPGA 7K690T的PCIE接口调试记录-续

上文https://blog.csdn.net/fzktongyong/article/details/134963814?spm1001.2014.3001.5501 上一篇文中PCIE实测速度和理论计算有较大偏差&#xff0c;经过尝试后有所提升。 1、提升效果 1&#xff09;、RC写操作&#xff0c;实测速度817MB/s&#xff08;410407&…

SQL进阶 | 外连接

概述 外连接的进阶用法在行列转换中比较有优势&#xff0c;往往存在需要把数据库中的格式转换成报表格式&#xff0c;但是SQL仅仅只是查询数据的语言&#xff0c;格式转换并不是原本的用途。 全外连接 标准 SQL 里定义了外连接的三种类型&#xff0c;如下所示。 左外连接&…

SpringBoot - application.yml 多环境切换解决方案

问题描述 这个问题玩过 SpringCloud 的小伙伴估计会想到用 bootstrap.yml 来解决这个问题。但是如果说为了解决这个问题引入了一堆的 SpringCloud Jar&#xff0c;就感觉杀鸡用牛刀。 于是今天我们想只有 application.yml 自己就可以解决这个问题&#xff0c;如何搞定&#x…

nginx常用命令及配置文件说明

目录 1 前言2 nginx常用命令2.1 查看 Nginx 版本号2.2 启动 Nginx2.3 停止 Nginx2.4 重新加载 Nginx 配置 3 Nginx配置文件说明3.1 **全局块**3.2 **Events 块**3.3 **HTTP 块** 4 结语 1 前言 使用 Nginx 作为 Web 服务器是构建现代网络基础架构的关键一环。在运维和开发领域…

【Socket】Unix环境下搭建简易本地时间获取服务

本文搭建一个Unix环境下的、局域网内的、简易的本地时间获取服务。 主要用于验证&#xff1a; 当TCP连接成功后&#xff0c;可以在两个线程中分别进行读操作、写操作动作当客户端自行终止连接后&#xff0c;服务端会在写操作时收到 SIGPIPE 信号当客户端执行shutdown写操作后&…

kettle+report designer导出带样式的excel包含多个sheet页

场景介绍&#xff1a; 运用pentaho report designer报表设计器&#xff0c;查询数据库字典表生成带有样式的excel&#xff0c;通过kettle pentaho报表输出组件导出形成数据字典&#xff0c;最终形成的数据字典样式如下图&#xff1a; 案例适用范围&#xff1a; pentaho repor…