I have a class with a property (signature
in the toy example below).
Some validation must be done, therefore there is a setter (@signature.setter
).
class Signature:
def __init__(self, input_array):
self.signature = input_array
@property
def signature(self):
return self._signature
@signature.setter
def signature(self, input_array):
arr = np.array(input_array)
if arr.ndim > 1:
raise ValueError("Only one-dimensional arrays are accepted!")
arr = np.unique(arr)
if any(arr <= 0):
raise ValueError("Only positive numbers are accepted!")
self._signature = arr
lst = [2,3,4]
s = Signature(lst)
s.signature
# array([2, 3, 4])
But then I can write:
s.signature = [4, 5, 6]
and everything will work just fine because there is a @signature.setter
.
Now what I want is to protect s.signature
from being set after this concrete object is created.
Should I use @property inside __new__
? How can I do this?
(I'm aware of How to restrict setting an attribute outside of constructor? discussion, but there is no setter there...)
You could make the setter raise an exception if one tries to set signature
. Just use a different method to check the value passed to __init__
and set it:
import numpy as np
class Signature:
def __init__(self, input_array):
self._check_and_set_signature(input_array)
@property
def signature(self):
return self._signature
@signature.setter
def signature(self, value):
raise ValueError("signature already set")
def _check_and_set_signature(self, input_array):
arr = np.array(input_array)
if arr.ndim > 1:
raise ValueError("Only one-dimensional arrays are accepted!")
arr = np.unique(arr)
if any(arr <= 0):
raise ValueError("Only positive numbers are accepted!")
self._signature = arr
Sample run:
lst = [2,3,4]
s = Signature(lst)
print(s.signature)
# array([2, 3, 4])
s.signature = [4, 5, 6]
[2 3 4]
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-6-68b91a667238> in <module>
30 # array([2, 3, 4])
31
---> 32 s.signature = [4, 5, 6]
<ipython-input-6-68b91a667238> in signature(self, value)
11 @signature.setter
12 def signature(self, value):
---> 13 raise ValueError("signature already set")
14
15
ValueError: signature already set