title: Python attributes and numpy arrays
body: <p>I have a class that stores some attributes. These attributes are numpy arrays with some floats inside. I want this attributes to be accessed when creating objects. What I don't want is them to be modified if any operation is done to a external variable that holds the value of the attribute.</p>
  
  <p>This is simple to do with getters/setters or properties with other types of variables, but it seems to fail with numpy arrays.</p>
  
  <p>I have wrote a simple script that tests every kind of possible solution I know. It works for integer attributes but fails with numpy arrays.</p>
  
  <p>This is the test class:</p>
  
  <pre><code>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
  </code></pre>
  
  <p>Testting it with integers as attributes:</p>
  
  <pre><code>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
  </code></pre>
  
  <p>Output as expected, without the attributes being modified externally:</p>
  
  <pre><code>10
  100
  1000
  10
  100
  1000
  </code></pre>
  
  <p>Testing it with numpy arrays:</p>
  
  <pre><code>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
  </code></pre>
  
  <p>Output not as expected, the values have been changed:</p>
  
  <pre><code>[10 20 30]
  [100 200 300]
  [1000 2000 3000]
  [15 25 35]
  [150 250 350]
  [1500 2500 3500]
  </code></pre>
  
  <p>So if not getters/setters nor properties work with numpy arrays, what can be done?</p>
  
  <p>EDIT:</p>
  
  <p>Well, I found a solution to this problem using the <code>copy.deepcopy</code> function. Now it works as expected.</p>
  
  <p>Attribute definition:</p>
  
  <pre><code>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
  </code></pre>
  
  <p>Testing:</p>
  
  <pre><code>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()
  </code></pre>
  
  <p>Result:</p>
  
  <pre><code>...
  [10000 20000 30000]
  ...
  [10000 20000 30000]
  </code></pre>