Python attributes and numpy arrays

I have a class that stores some attributes. These attributes are numpy arrays with some floats inside. I want these attributes to be available when creating objects. I do not want them to be changed if any operation is performed for an external variable that contains the value of the attribute.

This is easy to do with getters / setters or properties with other types of variables, but it doesn't seem to work with numpy arrays.

I wrote a simple script that checks for any possible solution that I know. It works for integer attributes, but does not work with numpy arrays.

This is a test class:

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 

Checking it with integers as attributes:

 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 

The output, as expected, without external attributes:

 10 100 1000 10 100 1000 

Testing with numpy arrays:

 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 

The output is not as expected, the values ​​have been changed:

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

So, if getters / seters or properties with numpy arrays do not work, what can be done?

EDIT:

Well, I found a solution to this problem using the copy.deepcopy function. Now it works as expected.

Attribute Definition:

 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 

Testing:

 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() 

Result:

 ... [10000 20000 30000] ... [10000 20000 30000] 
0
source share
1 answer

NumPy arrays are mutable, integers are not.

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

Note id .

Unlike:

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

Note : id remains the same.

It doesn't matter that you use a = test.get_attr1() or a = test.attribute2 . a you get is a Python object, since almost all of this is the object you deal with in Python. If you have a , it doesn't matter how you created it either by assigning a = 1 or as the return value from the a = test.get_attr1() method (the property just makes the syntax for calling the method more enjoyable.). Then a is just the name for the object, and you are working with this object. If it is modified like NumPy arrays, += usually changes the values ​​inside. For the immutable, it is simply impossible.

If you do not want to modify these objects, you can view a copy. Usually using the copy module. NumPy arrays provide their own copy method:

 >>> 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]) 
+3
source

Source: https://habr.com/ru/post/1267021/


All Articles