为何修改Python类的单个实例会导致所有实例及原数组发生变化?
Python中Numpy数组作为类属性的共享修改问题解答
问题场景
你遇到的情况是:用同一个Numpy数组初始化两个类实例的属性后,修改其中一个实例的属性,另外一个实例的属性甚至原数组都跟着变了,但用标量就不会有这个问题。你的测试脚本和输出如下:
测试脚本
import numpy as np s = np.array([1,2,3]) class test_class: def __init__(self,vv): self.v = vv def add(self,h,i): aux = self.v aux[i] += h self.v = aux tt1=test_class(s) tt2=test_class(s) tt1.add(1,0) print('s = ', s) print('tt1.v = ',tt1.v) print('tt2.v = ',tt2.v)
输出结果
s = [2 2 3] tt1.v = [2 2 3] tt2.v = [2 2 3]
原因解析
这本质是Python中可变对象与引用传递的特性在起作用,核心区别在于Numpy数组(可变对象)和标量(不可变对象)的处理方式:
- Numpy数组是可变对象:这类对象的特点是可以在原地修改内容,不需要创建新对象。当你用
s初始化tt1和tt2时,self.v = vv并没有复制整个数组,只是让tt1.v、tt2.v和s这三个变量都指向内存中同一个数组对象。后续add方法里的aux[i] += h是直接修改这个共享数组的内容,所以所有指向它的变量都会看到变化。 - 标量是不可变对象:像
int、float这类不可变对象,当你执行+=这类操作时,其实是创建了一个新的对象,而不是修改原来的。比如用s=1初始化实例后,修改tt1.v会生成新的整数赋值给它,tt2.v还是指向原来的1,自然不会跟着变。
解决方案
如果想让每个实例拥有独立的数组,互不影响,只需要在初始化时复制数组即可,修改__init__方法:
def __init__(self,vv): self.v = vv.copy() # 创建数组副本
内容的提问来源于stack exchange,提问作者Flixx
相关产品推荐
相关产品推荐

