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.pswp.cn/news/902818.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/902818.shtml
英文地址,請注明出處:http://en.pswp.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-- 勾選…