2013-06-05 69 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增加了有關複製的信息。感謝提示。 –