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

源代碼: Lib/copy.py


Python 的賦值語句不復制對象,而是創(chuàng)建目標和對象的綁定關(guān)系。對于自身可變,或包含可變項的集合,有時要生成副本用于改變操作,而不必改變原始對象。本模塊提供了通用的淺層復制和深層復制操作,(如下所述)。

接口摘要:

copy.copy(x)?

返回 x 的淺層復制。

copy.deepcopy(x[, memo])?

返回 x 的深層復制。

exception copy.Error?

針對模塊特定錯誤引發(fā)。

淺層與深層復制的區(qū)別僅與復合對象(即包含列表或類的實例等其他對象的對象)相關(guān):

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

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

深度復制操作通常存在兩個問題, 而淺層復制操作并不存在這些問題:

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

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

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

  • 保留在當前復制過程中已復制的對象的 "備忘錄" (memo) 字典;以及

  • 允許用戶定義的類重載復制操作或復制的組件集合。

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.

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

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

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

參見

模塊 pickle

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