2013-06-05 37 views
0

我有一些存储属性的类。这些属性是numpy数组,里面有一些浮点数。我想在创建对象时访问这些属性。我不想要的是,如果对包含该属性值的外部变量进行了任何操作,它们都将被修改。Python的属性和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] 

回答

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()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]) 
+0

我知道在对象类型中存在差异,在这种情况下可变对不可变。在我的编辑中,您可以看到我使用'copy'库在getter方法中提供numpy数组的深层副本,以便返回新的向量。这样我可以在不修改属性本身的情况下对数组进行操作。无论如何感谢提示,这真的很有价值。 –

+0

说实话,你的答案对于理解这些类型的对象之间的差异很有价值。但它并没有解决我的实际问题。我认为有人遇到我的问题会发现我​​的编辑比您的解释更有趣。无论如何,我接受你的。 –

+0

@IñigoHernáezCorres增加了有关复制的信息。感谢提示。 –