copy --- 淺層和深層複製操作

原始碼: Lib/copy.py


Python 中的賦值語句不復制物件,而是在目標和物件之間建立繫結。對於可變或包含可變項的集合,有時需要副本,以便可以更改一個副本而無需更改另一個。本模組提供了通用的淺層和深層複製操作(如下所述)。

介面摘要

copy.copy(obj)

返回 obj 的淺層複製。

copy.deepcopy(obj[, memo])

返回 obj 的深層複製。

copy.replace(obj, /, **changes)

建立一個與 obj 型別相同的新物件,並用 changes 中的值替換欄位。

在 3.13 版本加入。

exception copy.Error

針對模組特定錯誤引發。

淺層和深層複製之間的區別僅與複合物件(包含其他物件,如列表或類例項的物件)有關:

  • 淺層複製 會建立一個新的複合物件,然後(在可能的範圍內)將原始物件中元素的 引用 插入其中。

  • 深層複製 會建立一個新的複合物件,然後遞迴地將原始物件中元素的 副本 插入其中。

深層複製操作通常存在兩個淺層複製操作不存在的問題:

  • 遞迴物件(直接或間接包含對自身引用的複合物件)可能會導致遞迴迴圈。

  • 因為深層複製會複製所有內容,所以它可能會複製過多的資料,例如本應在副本之間共享的資料。

deepcopy() 函式透過以下方式避免了這些問題:

  • 保留一個 memo 字典,用於記錄在當前複製過程中已複製的物件;以及

  • 讓使用者自定義的類可以重寫複製操作或要複製的元件集。

此模組不復制模組、方法、棧跟蹤、棧幀、檔案、套接字、視窗或任何類似型別。它確實“複製”了函式和類(淺層和深層),透過返回原始物件而不做改變;這與 pickle 模組處理這些型別的方式是相容的。

字典的淺層複製可以使用 dict.copy() 來建立,列表的淺層複製可以透過對整個列表進行切片賦值來建立,例如 copied_list = original_list[:]

類可以使用與控制 pickling 相同的介面來控制複製。有關這些方法的資訊,請參閱 pickle 模組的描述。事實上,copy 模組使用了來自 copyreg 模組中已註冊的 pickle 函式。

為了讓一個類定義自己的複製實現,它可以定義特殊方法 __copy__()__deepcopy__()

object.__copy__(self)

呼叫以實現淺層複製操作;不傳遞額外引數。

object.__deepcopy__(self, memo)

呼叫以實現深層複製操作;它被傳遞一個引數,即 memo 字典。如果 __deepcopy__ 的實現需要對一個元件進行深層複製,它應該呼叫 deepcopy() 函式,並將該元件作為第一個引數,memo 字典作為第二個引數。memo 字典應被視為一個不透明物件。

函式 copy.replace()copy()deepcopy() 功能更受限,只支援由 namedtuple() 建立的命名元組、dataclasses 以及其他定義了 __replace__() 方法的類。

object.__replace__(self, /, **changes)

此方法應建立一個相同型別的新物件,並用 changes 中的值替換欄位。

在 3.13 版本加入。

參見

pickle 模組

關於用於支援物件狀態獲取和恢復的特殊方法的討論。