I would like to perform checks on the contents of a numpy array every time it is set. Can python properties be used for this? My approach:
import numpy as np
class Obj():
def __init__(self):
self._np_arr = None
@property
def np_arr(self):
if self._np_arr is None:
self._np_arr = np.ones(10)
return self._np_arr
@np_arr.setter
def np_arr(self, value):
if np.sum(value)>10:
raise ValueError('Error message')
self._np_arr = value
if __name__ == '__main__':
o = Obj()
print o.np_arr
o.np_arr = np.zeros(10) # ok
o.np_arr = np.ones(10)*2 # not ok
print o.np_arr
The getter is entered when the object is still None. Once np_arr is a numpy array the getters and setters no longer work.
What am I doing wrong?
First of all. This is difficult (up to, I believe impossible) to do right. The error here is quite simple, it must be a new style class. So just replace
class Obj()withclass Obj(object).This may not solve your problem however, since the user can still assign it in place, ie:
You could circumvent that somewhat by using
_np_arr.setflags(write=False), but then the user cannot use such operations at all.Edit:
you could also subclass ndarray, and define your own
__array_finalize__to circumvent that probably. However, even then the user could donp.asarray(o.np_arr)and modify that in place…I guess you could provide your own methods then “simulate” an array by wroking internally on a writeable one. But I doubt there is a 100% foolproof or at least elegent method.