python对象属性修改
python object attribute modification
这对我来说真的很令人惊讶(并且花费在调试上的时间成本很高):
class Test():
def __init__(self):
self.init_value = np.array([1, 2])
def func(self):
test = self.init_value
test[-1] = 0
return test
test = Test()
print(test.init_value)
test.func()
print(test.init_value)
我的问题是:
- 这是因为numpy数组的属性(深拷贝)吗?
- 有没有办法“修复”对象属性,除非我明确修改它们?
这是奇怪的参考与价值问题之一。
因为 self 是一个引用,所以你的测试变量是对 self.init_value...
的引用
所以你正在修改属性。 @matfux 的解决方案让您的变量存储 self.init_value 的副本而不是对它的引用。
老实说,在大多数 OOP 情况下,这是一个棘手的问题。
针对您的问题 1):
让我们先看看这里发生了什么,
self.init_value = np.array([1,2])
a np.array object 在内存中创建了提供的值,为此标签 self.init_value已分配。
现在,在这一步,
test = self.init_value
self.init_value指向的内存位置分配了另一个标签test。您可以通过如下修改 func() 来测试它:
def func():
test = self.init_value
# Both these values will be same.
print(hex(id(test)))
print(hex(id(self.init_value)))
test[-1] = 0
return test
所以当你执行 test[-1] = 0 时,你基本上是在访问 test 指向的对象的最后一个元素并将其更改为值 0,因为 self.init_value 和 test 指向同一个对象,它被修改了。
但是,如果您重新分配具有相同标签名称的其他对象,标签将从先前的对象中删除并附加到这个新对象。您可以使用代码检查内存位置来验证这一点:
hex(id(your_label))
关于你的问题 2:
如果不想test修改self.init_value,修改代码使用deepcopy()如下:
import copy
test = copy.deepcopy(self.init_value)
这对我来说真的很令人惊讶(并且花费在调试上的时间成本很高):
class Test():
def __init__(self):
self.init_value = np.array([1, 2])
def func(self):
test = self.init_value
test[-1] = 0
return test
test = Test()
print(test.init_value)
test.func()
print(test.init_value)
我的问题是:
- 这是因为numpy数组的属性(深拷贝)吗?
- 有没有办法“修复”对象属性,除非我明确修改它们?
这是奇怪的参考与价值问题之一。
因为 self 是一个引用,所以你的测试变量是对 self.init_value...
的引用所以你正在修改属性。 @matfux 的解决方案让您的变量存储 self.init_value 的副本而不是对它的引用。
老实说,在大多数 OOP 情况下,这是一个棘手的问题。
针对您的问题 1): 让我们先看看这里发生了什么,
self.init_value = np.array([1,2])
a np.array object 在内存中创建了提供的值,为此标签 self.init_value已分配。
现在,在这一步,
test = self.init_value
self.init_value指向的内存位置分配了另一个标签test。您可以通过如下修改 func() 来测试它:
def func():
test = self.init_value
# Both these values will be same.
print(hex(id(test)))
print(hex(id(self.init_value)))
test[-1] = 0
return test
所以当你执行 test[-1] = 0 时,你基本上是在访问 test 指向的对象的最后一个元素并将其更改为值 0,因为 self.init_value 和 test 指向同一个对象,它被修改了。
但是,如果您重新分配具有相同标签名称的其他对象,标签将从先前的对象中删除并附加到这个新对象。您可以使用代码检查内存位置来验证这一点:
hex(id(your_label))
关于你的问题 2:
如果不想test修改self.init_value,修改代码使用deepcopy()如下:
import copy
test = copy.deepcopy(self.init_value)