0

我有一个存储一些属性的类。这些属性是 numpy 数组,里面有一些浮点数。我希望在创建对象时访问此属性。如果对保存属性值的外部变量执行任何操作,我不希望它们被修改。

这对于 getter/setter 或具有其他类型变量的属性很简单,但对于 numpy 数组似乎失败了。

我写了一个简单的脚本来测试我知道的每一种可能的解决方案。它适用于整数属性,但适用于 numpy 数组。

这是测试类:

class test_class:

    # Initialization
    def __init__(self, attribute1, attribute2, attribute3):

        self.attribute1 = attribute1
        self._attribute2 = attribute2
        self._attribute3 = attribute3

# Attribute 1 with getter and setter
    def get_attr1(self):
        return(self.attribute1)

    def set_attr1(self, value):
        self.attribute1 = value

    # Attribute 2 as a property with getter and setter
    def get_attr2(self):
        return(self._attribute2)

    def set_attr2(self, value):
        self._attribute2 = value

    attribute2 = property(get_attr2, set_attr2)

    # Attribute 3 as a property
    @property
    def attribute3(self):
        return(self._attribute3)

    @attribute3.setter
    def attribute3(self, value):
        self._attribute3 = value

使用整数作为属性对其进行测试:

test = test_class(10, 100, 1000)

print test.get_attr1()
print test.attribute2
print test.attribute3

a1 = test.get_attr1()
a2 = test.attribute2
a3 = test.attribute3

a1 += 5
a2 += 50
a3 += 500

print test.get_attr1()
print test.attribute2
print test.attribute3

按预期输出,无需在外部修改属性:

10
100
1000
10
100
1000

使用 numpy 数组对其进行测试:

import numpy as np

test = test_class(np.array([10,20,30]), np.array([100,200,300]),   np.array([1000,2000,3000]))

print test.get_attr1()
print test.attribute2
print test.attribute3

a1 = test.get_attr1()
a2 = test.attribute2
a3 = test.attribute3

a1 += 5
a2 += 50
a3 += 500

print test.get_attr1()
print test.attribute2
print test.attribute3

输出不符合预期,值已更改:

[10 20 30]
[100 200 300]
[1000 2000 3000]
[15 25 35]
[150 250 350]
[1500 2500 3500]

因此,如果 getter/setter 和属性都不能与 numpy 数组一起使用,那该怎么办?

编辑:

好吧,我使用该功能找到了解决此问题的copy.deepcopy方法。现在它按预期工作。

属性定义:

from copy import deepcopy

class test_class:

    ...

    # Attribute 4 with getter and setter using deepcopy
    def get_attr4(self):
        return(deepcopy(self.attribute4))

    def set_attr4(self, value):
        self.attribute4 = value

测试:

test = test_class(np.array([10,20,30]), np.array([100,200,300]), np.array([1000,2000,3000]), np.array([10000,20000,30000]))

...
print test.get_attr4()
...
a4 = test.get_attr4()
...
a4 += 5000
...
print test.get_attr4()

结果:

...
[10000 20000 30000]
...
[10000 20000 30000]
4

1 回答 1

3

NumPy 数组是可变的,整数不是。

>>> a = 1
>>> id(1)
4297261152
>>> a += 1
>>> id(a)
4297261184

注意id更改。

相对于:

>>> arr = np.arange(5)
>>> d(arr)
4331954736
>>> arr += 10
>>> id(arr)
4331954736
>>> arr
array([10, 11, 12, 13, 14])

注意id保持不变。

a = test.get_attr1()使用or并不重要a = test.attribute2。你得到的a是一个 Python 对象,因为几乎所有东西都是你在 Python 中处理的一个对象。一旦你有了a它,无论你是如何通过赋值a = 1或作为方法的返回值来创建它的a = test.get_attr1()(该属性只是为方法调用提供了更好的语法。)。然后a只是一个对象的名称,您可以使用该对象。如果它像 NumPy 数组一样是可变的,则+=通常会更改内部的值。对于不可变的,这根本不可能。

如果你不想修改这些对象,你可以男性复制一份。通常在模块的帮助下copy。NumPy 数组提供了自己的复制方法:

>>> arr2  = arr.copy()
>>> arr
array([10, 11, 12, 13, 14])
>>> arr2 += 100
>>> arr2
array([110, 111, 112, 113, 114])
>>>  arr
array([10, 11, 12, 13, 14]) 
于 2013-06-05T13:45:01.650 回答