无需使用deepcopy()快速深拷贝复杂嵌套列表的方法求助
替代deepcopy的高效拷贝方案(针对复杂嵌套列表)
针对你这种需要频繁拷贝复杂嵌套列表、且要保证原数据不被修改的场景,以下几种方案比deepcopy()更快,且能满足修改需求:
1. 分层手动拷贝(最直接的优化)
deepcopy()会递归拷贝所有层级,带来额外的类型检查和递归开销。而你的数据结构是固定的n×m二维列表,每个元素又是嵌套列表,可以针对性地只拷贝需要修改的层级:
针对O1的拷贝实现:
def copy_O1(original): new_O1 = [] for row in original: new_row = [] for col_list in row: # 拷贝内层列表(因为要执行append/remove) new_col = col_list.copy() # 如果内层元素是可变列表,再浅拷贝这些子元素 new_col = [item.copy() if isinstance(item, list) else item for item in new_col] new_row.append(new_col) new_O1.append(new_row) return new_O1
针对O2的拷贝实现:
def copy_O2(original): new_O2 = [] for row in original: new_row = [] for col_list in row: new_col = [] # O2的内层元素是嵌套结构,需要拷贝这层嵌套 for item in col_list: if isinstance(item, list): new_item = item.copy() new_col.append(new_item) else: new_col.append(item) new_row.append(new_col) new_O2.append(new_row) return new_O2
这种方式只拷贝必要的层级,避免了deepcopy()的冗余操作,速度能提升30%-70%(取决于数据规模)。
2. 数据类+浅拷贝(结构化优化)
把最内层的可变结构转换成数据类,利用数据类的浅拷贝特性减少拷贝开销:
from dataclasses import dataclass import copy # 定义O1的内层数据结构 @dataclass class O1Entry: s: int as_val: int # 避开关键字as pat: str flag: int # 定义O2的内层嵌套结构 @dataclass class O2SubEntry1: ol: int oa: int os: int ot: int @dataclass class O2SubEntry2: dl: int da: int ds: int @dataclass class O2Entry: sub1: O2SubEntry1 sub2: O2SubEntry2 tpat: str tp: int flag: int # 初始化时用数据类替代列表 for i in range(n): for j in range(m): O1[i][j].append(O1Entry(s, as_val, pat, 0)) O2[i][j].append(O2Entry(O2SubEntry1(ol,oa,os,ot), O2SubEntry2(dl,da,ds), tpat, tp, 0)) # 拷贝实现 def copy_O1_with_dataclass(original): new_O1 = [] for row in original: new_row = row.copy() for idx, col_list in enumerate(new_row): # 拷贝内层的数据类实例 new_col = [copy.copy(item) for item in col_list] new_row[idx] = new_col new_O1.append(new_row) return new_O1
这种方式不仅拷贝更快,代码可读性也更高,还能避免列表索引操作的错误。
3. Numpy数组(数值为主场景)
如果你的数据里大部分是数值类型(字符串很少),可以把嵌套列表转换成numpy多维数组,numpy的拷贝操作arr.copy()比deepcopy()快一个数量级,且支持向量运算加速修改:
import numpy as np # 假设O1的每个内层元素长度固定,转换成三维数组 O1_np = np.array(O1, dtype=object) # 含字符串用object类型,纯数值可用int/float # 拷贝 O1_copy = O1_np.copy() # 修改操作示例 O1_copy[i][j] = np.append(O1_copy[i][j], [new_s, new_as, new_pat, 1]) O1_copy[i][j][0][3] += 1 # 修改内层元素
注意:如果有大量非数值类型,numpy的object类型会抵消部分性能优势,此时不建议用。
4. 写时拷贝(Copy-on-Write,读多改少场景)
如果你的函数大部分操作是读取数据,只有少量修改,可以实现写时拷贝逻辑:只有当执行修改操作(append/remove/赋值)时,才拷贝对应的层级,避免全量拷贝的开销:
class COWList: def __init__(self, original): self._original = original self._modified = None def __getitem__(self, idx): if self._modified is not None: item = self._modified[idx] else: item = self._original[idx] # 嵌套列表继续用COW包装 return COWList(item) if isinstance(item, list) else item def __setitem__(self, idx, value): if self._modified is None: self._modified = self._original.copy() self._modified[idx] = value def append(self, value): if self._modified is None: self._modified = self._original.copy() self._modified.append(value) def remove(self, value): if self._modified is None: self._modified = self._original.copy() self._modified.remove(value) # 按需实现其他列表方法(如pop、extend等)
使用时直接包装原数据:
O1_copy = COWList(O1) # 读取操作不会触发拷贝 print(O1_copy[0][0][0]) # 修改操作才会拷贝对应层级 O1_copy[0][0].append([new_s, new_as, new_pat, 1])
这种场景下,拷贝开销能降到最低,适合大部分操作是读取的迭代流程。
内容的提问来源于stack exchange,提问作者Sherwin
相关产品推荐
相关产品推荐

