Python原型模式介绍、使用;浅拷贝/深拷贝原理

一、Python原型模式(Prototype Pattern)简介

        1. 概念

原型模式是一种创建型设计模式,它通过复制(克隆)现有对象来创建新对象。这样可以避免使用复杂的构造函数来创建对象,提高程序的性能和可维护性。

        2. 功能

原型模式的功能是通过复制现有对象来创建新对象,从而提高程序的性能和可维护性。

        3. 优点

  • 可以避免重复创建相同的对象,提高性能;
  • 可以更加方便地创建复杂对象,减少代码的量;
  • 可以通过克隆来获取对象,避免了使用复杂的对象构造函数。

        4. 缺点

  • 实现对象克隆方法需要一定的技巧性,对开发者的要求较高;
  • 克隆方法可能需要比使用构造函数创建对象更加复杂。

        5. 应用场景

  • 在需要频繁创建相同对象的场景中,原型模式可以提高程序的性能;
  • 在需要创建复杂对象的场景中,原型模式能够简化对象创建的过程。

        6. 使用方式

在 Python 中,可以通过实现 __copy__()__deepcopy__() 方法来实现原型模式。其中,__copy__() 方法用于浅拷贝,__deepcopy__() 方法用于深拷贝。

        在 Python 中,许多内置的数据类型和标准库中的对象都实现了原型模式,如:字典、列表、集合、datetime 对象等。在自己的代码中,我们也可以使用原型模式来减少代码的量,提高程序的性能。特别是在需要创建大量相似对象的场景中,使用原型模式可以帮助我们大大提高效率。

二、原型模式使用:

原型模式是一种设计模式,它允许我们通过复制现有的对象来创建新的实例。在 Python 中,原型模式可以通过 copy 模块中的 copy()deepcopy() 函数来实现。

下面是一个简单的例子,说明如何使用原型模式创建新的对象:

        我们定义了一个 Person 类,该类有一个 clone() 方法,该方法使用 deepcopy() 函数来复制 Person 对象并返回一个新的实例。此外,该方法还接受一个可选的 kwargs 参数,该参数是一个字典,可以用来更新新的对象的属性。

现在,我们可以创建 Person 对象,并使用 clone() 方法创建一个新的实例。例如:

import copy
class Person():def __init__(self, name, age):self.name = nameself.age = age# 使用 print() 函数或字符串格式化操作符 % 将对象打印为字符串时,实际上是调用了该对象的 __str__() 方法def __str__(self): # __str__() 用于返回类的字符串表示形式return 'Person(name={}, age={})'.format(self.name, self.age)def clone(self, **kwargs):print("*********开始克隆")clone_obj = copy.deepcopy(self)clone_obj.__dict__.update(kwargs)return clone_objp1 = Person("Alice", 28)
p2 = p1.clone(name="Bob")
p3 = p1.clone(name="Charlie", age=30)
print(p1, p1.name, p1.age)
print(p2, p2.name, p2.age)
print(p3, p3.name, p3.age)

运行上述代码,输出结果为:

*********开始克隆
*********开始克隆
Person(name=Alice, age=28) Alice 28
Person(name=Bob, age=28) Bob 28
Person(name=Charlie, age=30) Charlie 30

从上面的输出结果可以看出,我们可以通过原型模式创建新的对象,并使用可选的参数来修改属性。这种模式非常适用于那些需要创建大量相似对象的场景,例如许多游戏中的敌人或NPC对象。

三、浅拷贝/深拷贝

浅拷贝和深拷贝都是 Python 中用来复制对象的方式。

  1. 概念:

    1. 浅拷贝(Shallow Copy):复制对象时,创建一个新对象,但该对象的某些属性仍然引用原始对象中的属性对象。
    2. 深拷贝(Deep Copy):复制对象时,创建一个新对象,并对原始对象中的所有属性进行递归复制。
  2. 工作原理:

    1. 浅拷贝:浅拷贝创建的新对象,其属性对象还是和原始对象中的属性对象相同。这意味着,如果修改新对象的属性对象,则原始对象和其他浅拷贝对象中的相同属性对象也会发生变化。
    2. 深拷贝:深拷贝创建的新对象和原始对象完全独立。这意味着,如果修改新对象的属性对象,则原始对象和其他深拷贝对象中的相同属性对象不会受到影响。
  3. 优点:

    1. 浅拷贝:比起深拷贝,浅拷贝更加高效,因为它不需要递归复制所有属性。同时,浅拷贝可以避免不必要的内存占用。
    2. 深拷贝:深拷贝可以保证复制后的对象和原始对象完全独立,不会出现因为共享引用导致的修改冲突问题。
  4. 缺点:

    1. 浅拷贝:由于浅拷贝只是复制了对象的引用,所以在修改属性对象时,会影响到原始对象和其他浅拷贝对象中的相同属性对象。
    2. 深拷贝:由于递归复制对象属性,所以深拷贝可能会消耗大量的内存和时间。
  5. 使用场景:

    1. 浅拷贝:当需要复制对象,但不需要深入复制对象属性时使用。比如,复制一个列表,但不需要复制列表中的元素。
    2. 深拷贝:当需要完全独立的副本时使用。比如,复制一个对象,但需要修改复制后的对象而不会影响原始对象。

Python 中实现浅拷贝和深拷贝的方式分别是 copydeepcopy 方法。例如:

import copy# a = [1,2]
a = [[1,2], [3,4]]
b = copy.copy(a)
print(a,b)
# b[1] = 3
b[1][1] = 5
print(a,b)a = [[1,2], [3,4]]
b = copy.deepcopy(a)
print(a,b)
b[1][1] = 5
print(a,b)

运行结果:

[[1, 2], [3, 4]] [[1, 2], [3, 4]]
[[1, 2], [3, 5]] [[1, 2], [3, 5]]
[[1, 2], [3, 4]] [[1, 2], [3, 4]]
[[1, 2], [3, 4]] [[1, 2], [3, 5]]

四、Python相关方法介绍

1. __str__() 方法介绍

在 Python 中,__str__() 方法是一种特殊的方法,用于返回类的字符串表示形式。当我们使用 print() 函数或字符串格式化操作符 % 将对象打印为字符串时,实际上是调用了该对象的 __str__() 方法。

通常情况下,__str__() 方法返回的字符串应该是可读性较好的字符串,方便人类阅读。比如,如果一个类 Person 表示一个人的信息,我们可以在该类中定义如下的 __str__() 方法:

class Person:def __init__(self, name, age):self.name = nameself.age = agedef __str__(self):return 'Person(name={}, age={})'.format(self.name, self.age)

在上面的例子中,__str__() 方法返回了一个类似于 Person(name=Alice, age=28) 的字符串表示形式,表示该对象的名字和年龄信息。通过这种方式,我们可以方便地打印或记录对象的信息,便于开发和调试。

需要注意的是,__str__() 方法应该返回一个字符串类型的值,否则会抛出 TypeError 异常。

2.__init__(self) 方法介绍

在 Python 中,__init__(self) 是一种特殊的方法,用于在创建一个新的对象时初始化该对象的属性。该方法在类中只能被定义一次,通常用于定义类的属性及其初始值。

在 Python 中,每次创建一个新的对象时,都会自动调用该对象所属类的 __init__(self) 方法进行初始化。在 __init__(self) 方法中,可以通过 self 参数来访问该对象的属性,从而给属性设置初始值。

例如,假设我们有一个类 Person 表示一个人的信息,可以在该类中定义如下的 __init__(self) 方法:

class Person:def __init__(self, name, age):self.name = nameself.age = age

在上面的例子中,__init__(self) 方法定义了两个参数 nameage,并将它们分别赋值给了对象的 nameage 属性。在创建一个新的 Person 对象时,可以通过传递相应的参数来初始化该对象的属性,例如:

p1 = Person('Alice', 28)
p2 = Person('Bob', 30)

在上面的例子中,我们分别创建了两个 Person 对象,并传递了不同的参数,从而初始化了这两个对象的属性。

3.del关键字介绍

在 Python 中,del 是一种关键字,用于删除对象或对象属性。当使用 del 关键字时,它会执行对应对象的 __del__() 方法,方法内可以进行一些清理操作,通常在不再需要对象时使用。

使用 del 关键字可以删除一个对象,例如:

x = 10     # 创建一个整数对象
del x     # 删除该对象

使用 del 关键字也可以删除一个对象的属性,例如:

class Person:def __init__(self, name, age):self.name = nameself.age = agep = Person('Alice', 28)
del p.age       # 删除 p 对象的 age 属性

在上面的例子中,我们先创建了一个 Person 对象 p,然后使用 del 关键字删除了它的 age 属性。删除属性时不会影响对象本身的存在,只是将属性删除。

需要注意的是,在类中定义了 __del__() 方法并不能确保它会被立即执行。对于垃圾回收机制,Python 中的实现是引用计数机制,当一个对象的引用计数为 0 时,Python 会自动调用它的 __del__() 方法。但是,由于引用计数并不是完全准确的,因此 __del__() 方法可能会有延迟执行的情况,不能依赖它进行一些重要的操作。

4.obj.__dic__.update(kwargs)介绍

在 Python 中,obj.__dict__ 是一个字典,用于存储对象的属性和值。而 kwargs 则是一个字典,包含键值对,表示要更新的属性和值。

obj.__dict__.update(kwargs) 表示将 kwargs 字典中的键值对更新到 obj 对象的 __dict__ 中。也就是说,使用 update() 方法可以动态地修改对象的属性值,这在某些情况下是非常有用的。

例如,在实例化对象的时候,如果需要动态地为对象设置属性,可以使用 __dict__update() 方法,如下所示:

class Person:def __init__(self, **kwargs):self.__dict__.update(kwargs)p = Person(name='Alice', age=28)
print(p.name)   # 输出:Alice
print(p.age)    # 输出:28

在上面的例子中,我们定义了一个 Person 类,可以接收任意数量的关键字参数。在实例化对象时,我们使用 __dict__update() 方法将关键字参数更新到对象的 __dict__ 中,从而动态地为对象设置属性。

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

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

相关文章

腾讯云tke-ingress开启ingress域名访问日志

容器类型为containers的tke集群控制台创建完ingress-controller之后,由于默认日志是打印在pod内的文件,现在需要自行收集访问日志,需要把日志打印在正常的pod输出上在收集 在ingress-controller中默认nginx配置为 access-log-path: /var/log…

redis 缓存穿透 缓存击穿 缓存雪崩

redis 缓存穿透 缓存击穿 缓存雪崩 1.缓存穿透 前提:应用服务器压力过大 > 导致redis命中率过低(查询不到缓存)> 一直查询数据库 描述:1.redis查询不到数据 2.出现很多非正常url访问(一般出现这些问题都是恶意…

独立站运营简历怎么写?如何做自建站履历?编写独立站经营履历的要点是什么?如何在简历中呈现个人自建站运营经验?

作为一名独立站运营者,一份出色的简历是展示自己能力的重要途径。一个精心制作的独立站运营简历可以为宝子们赢得心仪职位的机会。接下来,我们将介绍如何写一份引人注目的独立站运营简历,从而吸引雇主的目光。 独立站运营简历:个…

微服务——统一网关Getway

为什么需要网关? 网关的两种实现: 网关Getway——快速入门 步骤一 网关背身也是一个微服务,需要注册到nacos中去 步骤二 成功运行后 可以通过网关进行请求转发到对应服务。 流程如下: 路由断言工厂 网关路由可以配置的东西有如下。 spri…

【深度学习】yolov 图片训练的时候的遇到的warning: corrupt JPEG restored and saved

报错原因 是图片在dataset.py 走验证时报的错误。 if im.format.lower() in (jpg, jpeg):with open(im_file, rb) as f:f.seek(-2, 2)if f.read() ! b\xff\xd9: # corrupt JPEGImageOps.exif_transpose(Image.open(im_file)).save(im_file, JPEG, subsampling0, quality100)m…

Redis 九种数据类型的基本操作

一、redis9种数据类型的基本操作 ①key操作 #查找所有的key 127.0.0.1:6379> keys * 1) "pop" 2) "mylist" 3) "lpl" 4) "myset" #设置key的过期时间 返回1表示执行成功,0表示失败,出现问题 127.0.0.1:6379…

Qt Creator mainwindow.obj:-1: error: LNK2019

构建的时候报错: mainwindow.obj:-1: error: LNK2019: 无法解析的外部符号 "public: __thiscall mynotedig::mynotedig(class QWidget *)" (??0mynotedigQAEPAVQWidgetZ),该符号在函数 "public: void __thiscall MainWindow::mynoteab…

VMPWN的入门级别题目详解(一)

实验一 VMPWN1 题目简介 这是一道基础的VM相关题目,VMPWN的入门级别题目。前面提到VMPWN一般都是接收字节码然后对字节码进行解析,但是这道题目不接受字节码,它接收字节码的更高一级语言:汇编。程序直接接收类似”mov”、”add”…

前端面试题:探索前沿技术与知识深度的关键

在前端开发领域,面试是评估候选人技能和知识水平的重要环节。面试题涵盖了各个方面的前端知识,旨在考察候选人的理解能力和解决问题的能力。本文将介绍一些常见的前端面试题,并结合具体实例说明,帮助读者更好地理解和准备前端面试…

Dockerfile 创建镜像,构建LNMP+wordpress架构

目录 一、Dockerfile 构建镜像 1.Dockerfile 构建 nginx镜像 1.1创建 nginx Dockerfile 目录 1.2编写 Dockerfile 文件 1.3构建nginx镜像 2.Dockerfile 构建 mysql 镜像 2.1创建 mysql Dockerfile 目录 2.2修改mysql配置文件 2.3编写 Dockerfile 文件 2.4构建mysql镜…

[论文笔记] LLM数据集——金融数据集

一、chatglm_金融 ModelScope 魔搭社区 请将modelscope sdk升级到v1.7.2rc0,执行: ​ pip3 install "modelscope1.7.2rc0" -f https://modelscope.oss-cn-beijing.aliyuncs.com/releases/repo.html # 方式1 git clone http://www.modelscope…

Cesium态势标绘专题-圆角矩形(标绘+编辑)

标绘专题介绍:态势标绘专题介绍_总要学点什么的博客-CSDN博客 入口文件:Cesium态势标绘专题-入口_总要学点什么的博客-CSDN博客 辅助文件:Cesium态势标绘专题-辅助文件_总要学点什么的博客-CSDN博客 本专题没有废话,只有代码,代码中涉及到的引入文件方法,从上面三个链…

[RabbitMQ] RabbitMQ简单概述,用法和交换机模型

MQ概述: Message Queue(消息队列),实在消息的传输过程中保存消息的容器,都用于分布式系统之间进行通信 分布式系统通信的两种方式:直接远程调用 和 借助第三昂 完成间接通信 发送方称谓生产者,接收方称为消费者 MQ优…

JMeter基础入门教程之CSV数据文件设置CSV Data Set Config

最近在做压力测试,登录功能用到了配置元件:CSV 数据文件设置,可以将登录用户名和密码放在一个csv文件中,然后通过CSV数据文件设置元件读取出来,用来做压测。 一、CSV文件 CSV文件小知识分享:是指"逗号…

POC CPU 单核性能基准测试 Linux bash 下的简单测试用例 bc计算兀

指令 time echo "scale5000;4*a(1)" | bc -l -q 通过耗时简单评估CPU单核性能 测试环境一 yeqiangyeqiang-MS-7B23:/opt/cpu2006$ cat /etc/os-release PRETTY_NAME"Ubuntu 22.04.2 LTS" NAME"Ubuntu" VERSION_ID"22.04" VERSION&…

leetcode 620. 有趣的电影

# Write your MySQL query statement below select * from Cinema where id%21 and description !boring order by rating descid%21是筛选奇数的条件description !‘boring’ 是筛选不无聊的条件order by rating desc 按评分由大到小排序

Ubuntu 下安装软件,卸载,查看已经安装的软件

参考网址:http://wiki.ubuntu.org.cn/UbuntuSkills 一般的安装程序用三种: .deb 和.rpm 这两种安装文件 .bundle 这是二进制的安装文件  而 tar.gz 这类的只是压缩包(相当于 .rar,.zip 压缩包一样),如果此类文件是程序的话&a…

BP神经网络数据分类——语音特征信号分类(Matlab代码实现)

目录 💥1 概述 📚2 运行结果 🎉3 参考文献 👨‍💻4 Matlab代码 💥1 概述 BP神经网络是一种常见的人工神经网络,用于数据分类和回归等任务。在语音特征信号分类中,BP神经网络可…

qt画图大卫三角形电力

直接上code void paintEvent(QPaintEvent *event) {Q_UNUSED(event); QPainter painter(this); QRect rect0 = QRect(0,0,500,500);painter.drawRect(rect0);QRect rectB = QRect(-1,-1,501,501);painter.drawRect(rectB);//画三角形QLine line1 = QLine(QPoint(250.0f,80.0f),…

Android11 相机拍照权限,以及解决resolveActivity返回null

一、配置拍照和读写权限 <uses-permission android:name"android.permission.CAMERA"/> <uses-feature android:name"android.hardware.camera" /><uses-permission android:name"android.permission.WRITE_EXTERNAL_STORAGE"/&…