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)

我的问题是:

  1. 这是因为numpy数组的属性(深拷贝)吗?
  2. 有没有办法“修复”对象属性,除非我明确修改它们?

这是奇怪的参考与价值问题之一。

因为 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_valuetest 指向同一个对象,它被修改了。

但是,如果您重新分配具有相同标签名称的其他对象,标签将从先前的对象中删除并附加到这个新对象。您可以使用代码检查内存位置来验证这一点:

hex(id(your_label))

关于你的问题 2:

如果不想test修改self.init_value,修改代码使用deepcopy()如下:

import copy

test = copy.deepcopy(self.init_value)