You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

继承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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 08:48:02