Python @property(设置方法)限制只能在__init__方法中设置数据

1 投票
2 回答
1206 浏览
提问于 2025-04-18 14:33

我想创建一个对象,在这个对象初始化的时候(也就是在__init__()方法里)导入一些原始数据。不过,我希望从那时起这些数据只能读取,不能修改。我在考虑使用一个设置器属性self.raw_data,并想要实现以下逻辑:

@raw_data.setter
def raw_data(self, dataframe):
    <IF calling from __init__>?
        self.__raw_data = df

有没有办法让这个设置器方法知道它是在__init__里面被调用的?这样就可以阻止其他任何修改数据的尝试。

2 个回答

1

raw_data的设置方法里做的任何事情,都无法阻止直接给__raw_data赋值。我建议你不要定义设置方法,而是直接用__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]

这样做会让你的对象变成不可变的,但奇怪的副作用是你的对象现在变成了元组。

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

这样一来,这个设置器基本上就没什么用,所以你可以用更少的代码来跳过它(这会让这个属性变成只读的):

class Foo(object):
    def __init__(self, dataframe):
        self._raw_data = dataframe

    @property
    def raw_data(self):
         return self._raw_data

但是要注意,这些解决方案都无法阻止你直接设置_raw_data

撰写回答