[英]Python @property (setter method) that is restricted to setting data only in the __init__ method
I would like to setup an object that imports some raw_data during the initialization phase of the object (ie during the __init__()
method). 我想设置一个在对象的初始化阶段(即在
__init__()
方法期间__init__()
导入一些raw_data的对象。 However I would like to make it read only from that point on. 但是,从那时起,我只想读它。 I was thinking of using a setter property
self.raw_data
with the following logic: 我正在考虑使用具有以下逻辑的setter属性
self.raw_data
:
@raw_data.setter
def raw_data(self, dataframe):
<IF calling from __init__>?
self.__raw_data = df
Is there a way for the setter method to know if it is being called from within __init__
? setter方法是否有办法知道是否正在
__init__
中调用它? Blocking all other attempts to change the data. 阻止所有其他尝试更改数据的尝试。
The closest you can get is to only allow to set self._raw_data
if it hasn't be set yet, ie: 您可以获得的最接近的结果是仅允许设置
self._raw_data
如果尚未设置),即:
class Foo(object):
def __init__(self, dataframe):
self.raw_data = dataframe
@property
def raw_data(self):
return getattr(self, '_raw_data', None)
@raw_data.setter
def raw_data(self, dataframe):
if hasattr(self, '_raw_data'):
raise AttributeError, "Attribute is read-only")
self._raw_data = dataframe
Which makes the setter mostly useless, so you'd get the same result with less code skipping it (which will make the property read-only): 这使得setter几乎没有用,因此您可以通过更少的代码跳过它而获得相同的结果(这将使属性变为只读):
class Foo(object):
def __init__(self, dataframe):
self._raw_data = dataframe
@property
def raw_data(self):
return self._raw_data
But beware that none of these solutions will prevent you to directly set _raw_data
. 但是请注意,这些解决方案都不能阻止您直接设置
_raw_data
。
Nothing you do in the raw_data
setter is going to stop direct assignment to __raw_data
. 您在
raw_data
setter中所做的任何事情都不会停止对__raw_data
直接分配。 I would recommend not defining a setter and using __raw_data
for initialization. 我建议不要定义setter并使用
__raw_data
进行初始化。 This will block writes to raw_data
, but not __raw_data
. 这将阻止对
raw_data
写入,但不会__raw_data
。
If you want stricter enforcement, then by design, you don't have many options. 如果您想要更严格的执法,那么根据设计,您没有太多选择。 One option is to write your class in C or Cython.
一种选择是用C或Cython编写类。 The other option is easier, but it has awkward side effects.
另一个选项比较容易,但是副作用大。 That option is to subclass an immutable built-in type, such as
tuple
, and create pre-initialized instances with __new__
instead of mutating them into an initialized state with __init__
: 该选项是对不可变的内置类型(例如
tuple
)进行子类化,并使用__new__
创建预初始化的实例,而不是使用__init__
将它们变为初始化状态:
class Immutable(tuple):
__slots__ = [] # Prevents creation of instance __dict__
def __new__(cls, *whatever_args):
attribute1 = compute_it_however()
attribute2 = likewise()
return super(cls, Immutable).__new__(cls, attribute1, attribute2)
@property
def attribute1(self):
return self[0]
@property
def attribute2(self):
return self[1]
This makes your objects immutable, but the awkward side effect is that your objects are now tuples. 这使您的对象不可变,但是尴尬的副作用是您的对象现在是元组。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.