Python Cookbook-6.9 快速复制对象

任务

为了使用 copy.copy,需要实现特殊方法__copy__。而且你的类的__init__比较耗时所以你希望能够绕过它并获得一个“空的”未初始化的类实例。

解决方案

下面的解决方案可同时适用于新风格和经典类:

def empty_copy(obj):class Empty(obj.__class__):def __init__(self):passnewcopy = Empty()newcopy.__class__ = obj.__class__return newcopy

你的类可以使用这个函数来实现__copy__:

class YourClass(object):def __init__(self):assume there's a lot of work heredef __copy__(self):newcopy = empty_copy(self)copy some relevant subset of self's attributes to newcopyreturn newcopy

下面是用法示例:

if __name__ == '__main__':import copyy = YourClass()#很显然,__init__会被调用print z = copy.copy(y)y#…不调用__init__print z

讨论

如同 4.1节的讨论,当你进行赋值操作时,Python 并不会暗中对对象进行复制操作,这是一个很好的处理,因为这样的机制更快、更灵活,而且也具有语义的一致性。当需要复制时,要明确地提出请求,通常使用 copy.copy 函数,它知道怎样复制内建的类型,对于自定义的对象也具有默认的行为方式,如果你想定制这个复制过程,可以定义类的__copy__特殊方法。如果你的类实例是不允许复制的,可以定义一个__copy__并抛出一个 TypeError 异常。大多数情况下,你只需要让 copy.copy 按照默认的机制工作就可以很轻松地获得克隆能力。这确实是很棒的设计,其他很多语言会强迫你实现个特殊的 clone 方法来完成实例克隆。

如果__init__是一个耗时的操作,copy__常常需要以一个“空”实例开始,从而绕开__init。最简单和通用的方法是使用Python 提供的直接修改实例的类的能力:在本地的空类中创建一个新对象,然后设置此对象的class属性,如代码所示。对旧风格(经典)类而言,从obj.class__继承 Empty 类显得比较多余(但也没什么害处)但继承机制使得本节的方案对于各种对象包括经典的和新风格的类(包括内建的和扩展类型),都具有很好的兼容性。一旦你选择从ob的类继承,必须重写 Empty 类中的__init,否则就无法实现本节方案的初衷。重写,意味着obj类的__init__不会被执行,这是因为在 Python 中,父类的初始化方法并不会自动执行。

一旦得到了一个符合要求的类的“空”对象,就需要复制 self 属性的一个子集。当需要所有属性时,最好就不要自定义__copy__,因为copy.copy 的默认行为就是复制实例的所有属性。除非你除了复制所有属性之外还想做更多的工作,在本例中,下面两种复制所有属性的方式都是可行的:

newcopy.__dict__.update(self.__dict__)
newcopy.__dict__ = dict(self.__dict__)

新风格类的实例并不一定会在__dict__中保存它的所有状态,所以你可能需要复制一些与类相关特定的状态。

基于标准模块 new 的方式对于经典类和新风格类无法做到完全透明,而且new静态方法也不能生成一个空的实例——后者只在新风格类中存在。不过,本节的方案能够解决这些问题。

实现__copy__的一种好的替代方式是实现__getstate__和__setstate__方法:这些特殊方法以明确的和原生的方式定义了你的对象的状态,绕过了__init__。另外,它们也支持类实例的序列化:见7.4节中关于这些方法的更多信息。

到此为止我们讨论的是浅拷贝,这也是你大多数时候需要的复制方式。使用浅拷贝时虽然你的对象被复制了,但是它指向的很多对象(内部的属性或者子项)却并未被复制,所以新复制的对象和原对象指向相同的属性和子项–这是一种轻量级的快速操作。而深拷贝则是一种重量级的深度操作,它根据对象的指向图谱逐一地完成对所有对象的拷贝。可以调用 copy.deepcopy 完成对一个对象的深拷贝。如果你想定制你的类实例的深拷贝方式,需要定义一个特殊方法__deepcopy__:

class YourClass(object):'''def __deepcopy__(self,memo):newcopy = empty_copy(self)#使用copy.deepcopy(self.x,memo)来获得self的相关属性#元素的子集的深拷贝,并放入newcopy中。return newcopy

如果决定要实现__deepcopy__,记住要遵守Python 标准库模块 copy 的文档定义的memoization 协议——应该复制有第二个参数的 copy.deepcopy要求的全部属性和子项同一个memo字典,还会被传递给__deepcopy__方法。另外,实现__getstate__和__setstate__也是很好的选择,因为这些方法同样支持深拷贝:Python 会处理并复制那些由__getstate__ 返回的“状态”对象,然后传递给一个新的,空实例的__setstate__方法。参看7.4 节关于这些特殊方法的更多内容。

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

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

相关文章

kubernets集群的安装-node节点安装-(简单可用)-超详细

一、kubernetes 1、简介 kubernetes,简称K8s(库伯内特),是用8代替名字中间的8个字符“ubernete”而成的缩写 云计算的三种主要服务模式——基础设施即服务(IaaS)、平台即服务(PaaS&#xff0…

【Linux学习笔记】进程的fork创建 exit终止 wait等待

【Linux学习笔记】进程的fork创建 exit终止 wait等待 🔥个人主页:大白的编程日记 🔥专栏:Linux学习笔记 文章目录 【Linux学习笔记】进程的fork创建 exit终止 wait等待前言1.进程创建1.1 fork函数初识1.2fork函数返回值1.3写时拷…

鸿蒙应用开发证书考试的一点想法

一、介绍: 直接上图 二、体验后的想法: 1.知识点在指南API参考最佳实践里面找 2.没有明确说明考试不能查第1点的文档,但是考试只有1个小时,合理分配时间 3.切屏三次后自动提交要注意,每月3次机会下月又有3次机会&a…

含锡废水处理的经济效益

主要体现在成本节约和资源回收两方面,具体收益因处理工艺、废水浓度及规模差异而不同。以下结合不同技术路线进行量化分析: 一、直接经济效益 资源回收收益 金属锡回收: 若废水中锡浓度为100 mg/L,日处理量100吨,则每…

Base64编码原理:二进制数据与文本的转换技术

🔄 Base64编码原理:二进制数据与文本的转换技术 开发者的数据编码困境 作为开发者,你是否曾遇到这些与Base64相关的挑战: 📊 需要在JSON中传输二进制数据,但不确定如何正确编码🖼️ 想要在HT…

day49—双指针+贪心—验证回文串(LeetCode-680)

题目描述 给你一个字符串 s,最多 可以从中删除一个字符。 请你判断 s 是否能成为回文字符串:如果能,返回 true ;否则,返回 false 。 示例 1: 输入:s "aba" 输出:true…

Kubernetes(k8s) 集群的快速部署

实验目的 本实验旨在通过 Kubeadm 工具快速部署一个 Kubernetes 1.28.2 集群,包含 1 个 Master 节点和 2 个 Worker 节点,并验证集群的基本功能。实验涉及以下关键步骤: 环境准备:配置主机名、关闭防火墙、禁用 SELinux、设置时区…

7年经验的Java程序员的技术知识概览(及分阶段学习计划、资源推荐、职业发展建议)

🤟致敬读者 🟩感谢阅读🟦笑口常开🟪生日快乐⬛早点睡觉 📘博主相关 🟧博主信息🟨博客首页🟫专栏推荐🟥活动信息 文章目录 **一、技术栈全景与深度要求****1. 核心Java…

28、.NET 中元数据是什么?

在.NET中,元数据(Metadata)是描述程序结构和类型信息的二进制数据集合,它是.NET运行时(CLR)的核心基础组件之一,用于支持程序加载、类型解析、反射、安全校验等关键功能。以下是其核心特性和作用…

Idea中实用设置和插件

目录 一、Idea使用插件 1.Fitten Code智能提示 2.MyBatisCodeHelperPro 3.HighlightBracketPair‌ 4.Rainbow Brackets Lite 5.GitToolBox(存在付费) 6.MavenHelperPro 7.Search In Repository 8.VisualGC(存在付费) 9.vo2dto 10.Key Promoter X 11.CodeGlance…

Linux新手快速入门指南

Linux新手快速入门指南:从零到熟练的简明路线图 对于刚接触Linux的新手而言,这个开源世界既充满机遇又令人望而生畏。本文将通过系统化的学习路径和实战技巧,帮助您快速突破入门难关,掌握Linux核心技能。 一、突破认知误区&#x…

交叉编译paho.mqtt.c和paho.mqtt.cpp(MQTT客户端)

一、参考资料 【MQTT】paho.mqtt.cpp 库的 介绍、下载、交叉编译、MQTT客户端例子源码-CSDN博客 【MQTT】paho.mqtt.c 库的“介绍、下载、交叉编译” 详解,以及编写MQTT客户端例子源码-CSDN博客 二、准备工作 1. 重要说明 paho.mqtt.cpp与paho.mqtt.c&#xff…

Flink 源码编译

打包命令 打包整个项目 mvn clean package -DskipTests -Drat.skiptrue打包单个模块 mvn clean package -DskipTests -Drat.skiptrue -pl flink-dist如果该模块依赖其他模块,可能需要先将其他模块 install 到本地,如果依赖的模块的源代码有修改&#…

【Agent实战】从0到1开发一个Python 解释器 MCP SSE Server

写在前面 想象一个场景:LLM Agent(如 AutoGPT、MetaGPT 或我们自己构建的 Agent)在规划任务后,决定需要运行一段 Python 代码来处理数据或调用某个 API。它不能直接在自己的环境中执行(通常不具备这个能力,也不安全),而是需要将这段代码发送给一个专门的外部服务来执行…

HTML word属性

介绍 CSS word-spacing 属性,用于指定段字之间的空间,例如: p {word-spacing:30px; }word-spacing属性增加或减少字与字之间的空白。 注意: 负值是允许的。 浏览器支持 表格中的数字表示支持该属性的第一个浏览器版本号。 属…

assertEquals()

assertEquals() 是 JUnit 框架中用于进行断言操作的一个非常常用的方法,其主要目的是验证两个值是否相等。如果两个值不相等,测试就会失败,JUnit 会给出相应的错误信息,提示开发者测试未通过。下面为你详细介绍: 方法…

Nginx 反向代理,啥是“反向代理“啊,为啥叫“反向“代理?而不叫“正向”代理?它能干哈?

Nginx 反向代理的理解与配置 User 我打包了我的前端vue项目,上传到服务器,在宝塔面板安装了nginx服务,配置了文件 nginx.txt .运行了项目。 我想清楚,什么是nginx反向代理?是nginx作为一个中介?中间件来集…

用 Python 打造打篮球字符动画!控制台彩色炫酷输出,抖音搞怪视频灵感还原

一、引言:从抖音搞怪视频到 Python 字符动画的奇妙之旅 刷抖音时刷到一个神级操作 —— 博主用 01 数字矩阵还原了明星打篮球的经典画面,字符在控制台随动作节奏炫彩跳动,瞬间点燃了技术宅的 DNA!作为 Python 图像处理爱好者&…

《逐梦九天:中国航天编年史》

《逐梦九天:中国航天编年史》 新华社酒泉2025年4月24日电(记者李国利、黄一宸)神舟二十号载人飞船发射4月24日取得圆满成功,中国载人航天在“东方红一号”发射55载之际开启第20次神舟问天之旅。 当日17时17分,搭载神舟二十号载人飞船的长征二号F遥二十运载火箭在酒泉卫星…

IDEA搭建环境的五种方式

一、普通的java项目 File--New--Project 选择Java,jdk选择1.8版本,然后点next 输入项目名和路径名,点击Finish 创建包结构,编写Class类 编写主方法,输出Hello标志完成 二、普通的javaWeb项目 Java Enterprise-- 勾选…