继承np.ndarray的自定义类拷贝时修改副本导致原数组被改动
问题根因确认
你的定位完全正确:np.copy对dtype=object类型的数组仅执行浅拷贝,仅会生成新的数组容器,数组内存储的所有Cell实例还是和原数组指向同一个内存对象,修改Cell的value属性自然会同步到原数组上。
解决方案
方案1:使用标准库深拷贝(最简改法)
直接替换np.copy为Python标准库copy模块的deepcopy方法,它会递归复制所有嵌套的可变对象,生成完全独立的新Cell实例,同时会自动保留Custom类的类型。
修改后的代码如下:
import copy # 仅需修改modify函数中的拷贝逻辑即可 def modify(instance: Custom, move_from: tuple, move_to: tuple): new_instance = copy.deepcopy(instance) moving_cell = new_instance[move_from].value new_instance[move_to].value = moving_cell new_instance[move_from].value = Empty() return new_instance
方案2:手动实例化新Cell数组(性能更可控)
如果你不想引入深拷贝的隐式开销,也可以手动遍历原数组生成全新的Cell实例构建新的Custom对象:
def modify(instance: Custom, move_from: tuple, move_to: tuple): # 手动生成所有新Cell实例,完全和原数组隔离 new_instance = Custom([[Cell(cell.value) for cell in row] for row in instance]) moving_cell = new_instance[move_from].value new_instance[move_to].value = moving_cell new_instance[move_from].value = Empty() return new_instance
方案3:封装Custom类拷贝方法(可选优化)
如果需要频繁执行拷贝操作,可以在Custom类中封装深拷贝逻辑,简化调用:
import copy class Custom(np.ndarray): def __new__(cls, array_like): obj = np.asarray(array_like, dtype=object).view(cls) return obj def __array_finalize__(self, obj): if obj is None: return def copy(self): return copy.deepcopy(self)
后续直接调用new_instance = instance.copy()即可获取独立的Custom实例。
注意事项
如果你的数组规模非常大、Cell类属性多,深拷贝会产生更高的性能开销,你可以根据业务场景在性能和数据隔离性之间做权衡。
内容的提问来源于stack exchange,提问作者ToJestKrzysio
相关产品推荐
相关产品推荐

