我想设置一个对象,在对象的初始化阶段(即在__init__()
方法期间)导入一些raw_data。但是我想从那一点开始只读它。我正在考虑使用具有以下逻辑的setter属性self.raw_data
:
@raw_data.setter
def raw_data(self, dataframe):
<IF calling from __init__>?
self.__raw_data = df
有没有办法让setter方法知道是否从__init__
内调用它?
阻止所有其他更改数据的尝试。
答案 0 :(得分:1)
最接近的是,如果尚未设置,则仅允许设置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
这使得setter几乎无用,所以你可以用更少的代码跳过它来得到相同的结果(这将使属性成为只读):
class Foo(object):
def __init__(self, dataframe):
self._raw_data = dataframe
@property
def raw_data(self):
return self._raw_data
但请注意,这些解决方案都不会阻止您直接设置_raw_data
。
答案 1 :(得分:1)
您在raw_data
setter中所做的任何操作都不会停止直接分配到__raw_data
。我建议不要定义一个setter并使用__raw_data
进行初始化。这将阻止对raw_data
的写入,但不会阻止__raw_data
。
如果你想要更严格的执法,那么按照设计,你就没有多少选择。一种选择是用C或Cython编写你的类。另一种选择更容易,但它具有尴尬的副作用。该选项是子类化不可变的内置类型,例如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]
这使你的对象不可变,但是副作用很尴尬,你的对象现在是元组。