copy --- 淺層 (shallow) 和深層 (deep) 復(fù)制操作?

源代碼: Lib/copy.py


Python 的賦值語(yǔ)句不復(fù)制對(duì)象,而是創(chuàng)建目標(biāo)和對(duì)象的綁定關(guān)系。對(duì)于自身可變,或包含可變項(xiàng)的集合,有時(shí)要生成副本用于改變操作,而不必改變?cè)紝?duì)象。本模塊提供了通用的淺層復(fù)制和深層復(fù)制操作,(如下所述)。

接口摘要:

copy.copy(x)?

返回 x 的淺層復(fù)制。

copy.deepcopy(x[, memo])?

返回 x 的深層復(fù)制。

exception copy.Error?

針對(duì)模塊特定錯(cuò)誤引發(fā)。

淺層與深層復(fù)制的區(qū)別僅與復(fù)合對(duì)象(即包含列表或類(lèi)的實(shí)例等其他對(duì)象的對(duì)象)相關(guān):

  • 淺層復(fù)制 構(gòu)造一個(gè)新的復(fù)合對(duì)象,然后(在盡可能的范圍內(nèi))將原始對(duì)象中找到的對(duì)象的 引用 插入其中。

  • 深層復(fù)制 構(gòu)造一個(gè)新的復(fù)合對(duì)象,然后,遞歸地將在原始對(duì)象里找到的對(duì)象的 副本 插入其中。

深度復(fù)制操作通常存在兩個(gè)問(wèn)題, 而淺層復(fù)制操作并不存在這些問(wèn)題:

  • 遞歸對(duì)象 (直接或間接包含對(duì)自身引用的復(fù)合對(duì)象) 可能會(huì)導(dǎo)致遞歸循環(huán)。

  • 由于深層復(fù)制會(huì)復(fù)制所有內(nèi)容,因此可能會(huì)過(guò)多復(fù)制(例如本應(yīng)該在副本之間共享的數(shù)據(jù))。

deepcopy() 函數(shù)用以下方式避免了這些問(wèn)題:

  • 保留在當(dāng)前復(fù)制過(guò)程中已復(fù)制的對(duì)象的 "備忘錄" (memo) 字典;以及

  • 允許用戶定義的類(lèi)重載復(fù)制操作或復(fù)制的組件集合。

This module does not copy types like module, method, stack trace, stack frame, file, socket, window, or any similar types. It does "copy" functions and classes (shallow and deeply), by returning the original object unchanged; this is compatible with the way these are treated by the pickle module.

制作字典的淺層復(fù)制可以使用 dict.copy() 方法,而制作列表的淺層復(fù)制可以通過(guò)賦值整個(gè)列表的切片完成,例如,copied_list = original_list[:]。

類(lèi)可以使用與控制序列化(pickling)操作相同的接口來(lái)控制復(fù)制操作,關(guān)于這些方法的描述信息請(qǐng)參考 pickle 模塊。實(shí)際上,copy 模塊使用的正是從 copyreg 模塊中注冊(cè)的 pickle 函數(shù)。

想要為一個(gè)類(lèi)定義它自己的拷貝操作實(shí)現(xiàn),可以通過(guò)定義特殊方法 __copy__()__deepcopy__()。 調(diào)用前者以實(shí)現(xiàn)淺層拷貝操作;該方法不必傳入額外參數(shù)。 調(diào)用后者以實(shí)現(xiàn)深層拷貝操作;它應(yīng)轉(zhuǎn)入一個(gè)參數(shù),即 memo 字典。 如果 __deepcopy__() 實(shí)現(xiàn)需要?jiǎng)?chuàng)建一個(gè)組件的深層拷貝,它應(yīng)當(dāng)調(diào)用 deepcopy() 函數(shù)并以該組件作為第一個(gè)參數(shù)而以該 memo 字典作為第二個(gè)參數(shù)。。 memo 字典應(yīng)當(dāng)被當(dāng)作不透明對(duì)象來(lái)處理。

參見(jiàn)

模塊 pickle

討論了支持對(duì)象狀態(tài)檢索和恢復(fù)的特殊方法。