Python面经【8】- Python设计模式专题-上卷

Python面经【8】- Python设计模式专题-上卷

  • 一、接口
  • 二、单例模式
    • (1) 方法一:使用模块
    • (2) 方法二: 装饰器实现【手撕 + 理解】(单下划线 + 闭包 + 装饰器 + 类方法)
    • (3) 方法三:基于__new__方法【new和init 】

设计模式是一套 被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了重用代码、让代码更容易被他人理解、保证代码可靠性。

一、接口

定义:一种特殊的类,声明了若干方法,要求继承该接口的类必须实现这些方法,可以通过抽象基类(Abstract Base Class)来实现。
作用:限制继承接口的类的方法的名称调用方式,隐藏了类的内部实现。

 1. from abc import ABCMeta, abstractmethod2. class Payment(metaclass = ABCMeta):3. 	@abstractmethod4. 	def pay(self, money):5. 		pass6. 	7. class Payment_first(Payment):8. 	def pay(self, money):9. 		print("给%s块钱"%money)
10. 		
11. pay = Payment_first()
12. pay_first = Payment_first()
13. pay_first.pay(3)
14. 结果:给3块钱

二、单例模式

单例模式是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在。在系统中,某个类只能出现一个实例对象时,单例对象就能排上用场
定义:保证一个类只能有一个实例,而客户可以从一个众所周知的访问点访问它时。
优点: 1、在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例。
2、避免对资源的多重占用(比如写文件操作)。
比如,某个服务器程序的配置信息存放在一个文件中,客户端通过一个AppConfig的类来读取配置文件的信息。如果在程序运行期间,有很多地方都需要配置文件的内容,也就是说,很多地方都需要创建AppConfig对象的实例,这就导致系统中存在多个AppConfig的实例对象,而这样会严重浪费内存,类似于AppConfig这样的类,我们希望在程序运行期间只存在一个实例对象。

(1) 方法一:使用模块

实现方法:将需要实现的单例功能放到一个.py文件中
实现原理:Python的模块就是天然的单例模式,因为模块在第一次导入时,会生成.pyc文件,当第二次导入时,就会直接加载.pyc文件,而不会再次执行模块代码。因此,我们只需把相关的函数和数据定义在一个模块中,就可以获得一个单例对象了。

1. # singleton_module.py
2. class SingletonClass:
3. 	def __init__(self):
4. 		pass
5.  
6. singleton_instance = SingletonClass()

将上面的代码保存在文件singleton_module.py中,要使用时,直接在其他文件中导入此文件中的对象,这个对象既是单例模式的对象。

1. # main.py
2. from singleton_module import singleton_instance
3.  
4. # 使用singleton_instance

(2) 方法二: 装饰器实现【手撕 + 理解】(单下划线 + 闭包 + 装饰器 + 类方法)

定义一个装饰器函数,将被装饰的类实例保存在闭包中,每次获取实例时返回同一个实例对象。

 1.  1. def Singleton(cls):2.  2.     _instance = {}3.  3.     def _singleton(*args, **kargs):4.  4.         if cls not in _instance:#判断该实例是否存在,存在就直接返回,不存在就创建        5.  5.             _instance[cls] = cls(*args, **kargs)6.  6.         return _instance[cls]7.  7.     return _singleton8.  8.  9.  9. @Singleton
10. 10. class A(object):
11. 11.     a = 1
12. 12.     def __init__(self, x=0):
13. 13.         self.x = x
14. 14.  
15. 15. a1 = A(2)
16. 16. a2 = A(3)
17. 17. # 输出:{<class '__main__.A'>: <__main__.A object at 0x7fb9af751af0>}
18. ===输出结果===
19. <__main__.A object at 0x000001E9D1F099B0>
20. <__main__.A object at 0x000001E9D1F099B0>
  • 输出结果分析:
    • 输出显示两个实例的内存地址是相同的(0x000001E9D1F099B0),这证明 a1 和 a2 实际上是同一个实例的引用
    • 这证实了单例模式的实现,确保了类 A 无论被实例化多少次,始终只有一个实例存在

(3) 方法三:基于__new__方法【new和init 】

我们都知道,当我们实例化一个对象时,是先执行了类的__new__方法(我们没写时,默认调用object.new),实例化对象;然后再执行类的__init__方法,对这个对象进行初始化,所以我们可以基于这个,实现单例模式。
个人最初常用的是重写__new__方法的方式,但是用重写类中的__new__方法,在多次创建时,尽管返回的都是同一个对象,但是每次执行创建对象语句时,内部的__init__方法都会被自动调用,而在某些应用场景,可能存在初始化方法只能运行只能允许运行一次的需求,这是这种单例的方式并不可取。

 1. class Download(object):2. 	instance = None3. 	def __init__(self):4. 		print("__init__")5. 	def __new__(cls, *args, **kargs):6. 		if cls.instance is None:7. 			cls.instance = super().__new__(cls)8. 		return cls.instance9. object1 = Download()
10. object2 = Download()
11. print(object1)
12. print(object2)

运行结果,可以看到初始化方法多次执行了。

1. __init__
2. __init__
3. <__main__.Download object at 0x7f56beb4ea90>
4. <__main__.Download object at 0x7f56beb4ea90>  

init方法通常用在初始化一个类实例的时候,但其实它不是实例化一个类的时候第一个被调用的方法。当使用Student(id, name)这样的表达式来实例化一个类时,最先被调用的方法其实是new方法。
new方法接受的参数虽然也是和init一样,但init是在类实例创建之后调用,而new方法正式创建这个类实例的方法。
New为对象分配空间,是内置的静态方法,new在内存中为对象分配了空间也返回了对象的引用,init获得了这个引用才初始化这个实例。

Eg:示例
一个非常简单的单例

1. class A:
2. 	instance = None
3.  	def __new__(cls, *args, **kwargs):
4.            	if cls.instance is None:
5.                	       cls.instance = super().__new__(cls)
6.   		return cls.instance

因为new方法是一个静态方法(也就是在定义的时候就没有cls参数),所以在这里要传入一个cls参数,而且这里的new你改造过了,所以要返回爸爸的new方法。
按造这个方法改造的单例怎么new都是同一个实例,但init仍然会被执行多次,也就是创建了几个对象就调用几次初始化方法。所以还要对init再进行一些判断

 1.  1. class A:2.  2.  	instance = None3.  3.  	init_flag = False # 初始化标记4.  4.  5.  5.  	def __new__(cls, *args, **kwargs):6.  6.   		if cls.instance is None:7.  7.    	cls.instance = super().__new__(cls)8.  8.   		return cls.instance9.  9.  
10. 10.  	def __init__(self):
11. 11.   		if A.init_flag:
12. 12.    	return
13. 13.   		print('执行了初始化方法')
14. 14.   		A.init_flag = True
15. 15.  
16. 16. if __name__ == '__main__':
17. 17.  a = A()
18. 18.  b = A()
19. 19.  print(a)
20. 20.  print(b)
21. ===结果如下===
22. 执行了初始化方法
23. <__main__.A object at 0x000001E9D1F096D8>
24. <__main__.A object at 0x000001E9D1F096D8>

结果分析:

  • 执行了初始化
    这一行表明 init 方法被执行了一次。由于在 init 方法中有一个条件检查 (if A.init_flag:),它确保初始化代码块只执行一次。在第一次创建实例 a 时,init_flag 是 False,所以 init 方法的内部代码被执行,并且 init_flag 被设置为 True。当创建第二个实例 b 时,由于 init_flag 已经是 True,init 方法内的代码不会再次执行。
  • <main.A object at 0x000001E9D1F096D8>
    这两行输出分别是打印的 a 和 b 实例。它们具有相同的内存地址 (0x000001E9D1F096D8),这证明了 a 和 b 是同一个对象的两个引用。这符合单例模式的预期效果,即不管创建多少次该类的实例,始终只有一个实例存在。

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

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

相关文章

简单的 u-popup 弹出框

uniapp中的popup组件可以用于弹出简单的提示框、操作框、菜单等。它可以通过position属性控制弹出框的位置&#xff0c;不同的position值会使得弹出框呈现不同的弹出形式 目录 一、实现思路 二、实现步骤 ①view部分展示 ②JavaScript 内容 ③css中样式展示 三、效果展示 …

Linux系统---基于Pipe实现一个简单Client-Server system

顾得泉&#xff1a;个人主页 个人专栏&#xff1a;《Linux操作系统》 《C/C》 《LeedCode刷题》 键盘敲烂&#xff0c;年薪百万&#xff01; 一、题目要求 Server是一个服务器进程&#xff0c;只能进行整数平方运算。Client要计算一个整数的平方的平方的平方&#xff0c;即…

聊聊 Jetpack Compose 原理 -- 穿透刺客 CompositionLocal

Compose 官方说明一直很简洁&#xff1a;CompositionLocal 是通过组合隐式向下传递数据的工具。 我们先来看一段代码&#xff1a; class MainActivity : ComponentActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setCo…

datav-轮播排名-对数据进行处理

前言 对于大屏需求我们排名数据轮播也是经常需要用到的需求&#xff0c;datav也是给我们提供了 不是说我们自己不能写&#xff0c;而是提供好的轮子比我们自己 写的&#xff0c;更全面&#xff0c;更周到&#xff0c; 没有特殊需求的话&#xff0c;使用datav配置一下完成这个…

mysqlsh导入json,最终还得靠navicat导入json

工作需要将一个巨大的10G的json导入mysql数据库。 看到mysql官方有对json导入的支持。 如下&#xff1a; MySQL :: Import JSON to MySQL made easy with the MySQL Shell $ mysqlsh rootlocalhost:33300/test --import /path_to_file/zips.json Creating a session to root…

产品经理进阶:以客户为中心的8个维度

目录 简介 以客户为中心 流程和组织维度 产品维度 CSDN学院《硬件产品进阶课》

python:六种算法(DBO、RFO、WOA、GWO、PSO、GA)求解23个测试函数(python代码)

一、六种算法简介 1、蜣螂优化算法DBO 2、红狐优化算法RFO 3、鲸鱼优化算法WOA 4、灰狼优化算法GWO 5、粒子群优化算法PSO 6、遗传算法GA 二、6种算法求解23个函数 &#xff08;1&#xff09;23个函数简介 参考文献&#xff1a; [1] Yao X, Liu Y, Lin G M. Evolution…

读书笔记 | 自我管理的关键是提高执行力

哈喽啊&#xff0c;你好&#xff0c;我是雷工&#xff01; 有句话说&#xff0c;能管好自己才是真的本事。 自我管理&#xff0c;管好自己很重要。 我们之所以懂得这么多的道理&#xff0c;却依然过不好这一生&#xff1f; 很大部分原因是因为管不住自己&#xff0c;做不到。 …

性能测试基础

性能测试分类 客户端性能&#xff1a;测试APP自身的性能&#xff0c;例如CPU、内存消耗&#xff1b;web页面元素渲染速度 服务端性能&#xff1a;测试服务端项目程序的支持的并发、处理能力、响应时间等&#xff0c;主要通过接口来做性能测试 性能测试指标 并发 同时向服务…

大一作业习题

第一题&#xff1a;答案&#xff1a; #include <stdio.h> void sort(int a[], int m) //将数组a的前m个元素(从小到大)排序 {int i 0;for (i 0; i < m - 1; i){int j 0;int flag 1;for (j 0; j < m - 1 - i; j){if (a[j] > a[j 1]){int t 0;t a[j];…

Java八股文面试全套真题【含答案】- Servlet篇

以下是一些关于Servlet的经典面试题以及它们的答案&#xff1a; 什么是 Servlet&#xff1f; 答案&#xff1a;Servlet 是运行在服务器上&#xff0c;用于处理客户端请求并生成响应的 Java 类。 Servlet 和 JSP 之间的区别是什么&#xff1f; 答案&#xff1a;Servlet 是基于…

1.鸿蒙应用程序开发app_hap开发环境搭建

1.下载Node.js, Javascipts的运行环境 node.js版本下载v12.18.3/https://www.cnblogs.com/txwtech/p/17865780.html 2.下载并安装DevEco Studio DevEco Studio 3.1 DevEco Studio 3.1配套支持HarmonyOS 3.1版本及以上的应用及服务开发&#xff0c;提供了代码智能编辑、低代…

Docker笔记:Docker中简单配置Mysql/Redis/Mongodb容器

Docker 配置 Mysql 容器 1 &#xff09;方案1&#xff1a;基于centos等linux操作系统 启动centos镜像&#xff0c;在里面安装 mysql这样比较麻烦&#xff0c;配置的东西很多 … 2 &#xff09;方案2&#xff1a;直接用 mysql 镜像 (推荐) $ docker pull mysql 下载镜像$ do…

589. N 叉树的前序遍历

589. N 叉树的前序遍历 java1&#xff1a;stack栈&#xff1a;没看懂 class Solution {public List<Integer> preorder(Node root) {List<Integer> res new ArrayList<Integer>();if (root null) {return res;}Map<Node, Integer> map new HashMa…

C盘瘦身,C盘清理

以下只是我的C盘清理经验~ 一.【用软件简单清理C盘】 使用一些垃圾清理软件&#xff0c;简单的初步把C盘先清理一遍。&#xff08;这种软件太多我就不推荐了……&#xff09; 二.【WPS清理大师】 因为我电脑装了WPS&#xff0c;发现右键单击C盘有个选项【释放C盘空间】&#xf…

接口自动化框架(Pytest+request+Allure)

前言&#xff1a; 接口自动化是指模拟程序接口层面的自动化&#xff0c;由于接口不易变更&#xff0c;维护成本更小&#xff0c;所以深受各大公司的喜爱。 接口自动化包含2个部分&#xff0c;功能性的接口自动化测试和并发接口自动化测试。 本次文章着重介绍第一种&#xff0c…

Vue3.3.4中watch无法监测props的更改

背景 网上说了很多解决方案&#xff0c;都是通过watch(() > props.value, (newValue, oldValue) > {})解决&#xff0c;或者是加上{deep: true}附加属性。但是我在Vue3.3.4中&#xff0c;还是无法解决。 下面说一下我的解决方案。 解决方案 通过父组件调用子组件defineE…

点云/Mesh 常见处理库和软件汇总

注&#xff1a;参考 网址1、网址2 文章目录 软件通用点云/Mesh处理库通用几何处理库专用功能库 软件 Processing MeshLabCloudCompareTrimeshPyVistaVedo Visualization Simple-3dvizPlotOptiX (Requires CUDA-enabled GPU)PolyscopePyrender 通用点云/Mesh处理库 PCL &am…

【开发问题】vue的前端和java的后台,用sm4,实现前台加密,后台解密

sm4加密 vue引入的包代码加密解密 javamaven代码运行结果 vue 引入的包 npm install sm-crypto代码加密解密 加密&#xff1a; key &#xff1a;代表着密钥&#xff0c;必须是16 字节的十六进制密钥 password &#xff1a;加密前的密码 sm4Password &#xff1a;代表sm4加密…

Python之格式化保存数据点

功能&#xff1a;将平面点集存储为格式化txt文档&#xff0c;每个坐标值为5位整数&#xff0c;前三位为整数&#xff0c;后2位为小数 输入&#xff1a;平面点坐标&#xff0c;用列表存储&#xff0c;列表的元素为点坐标元组 输出&#xff1a;txt文件&#xff0c;每行一个点坐…