如何防止 Python 中的类字段(列表)更改?

例如,我有一个带有字段的类__x,它是一个列表:


class C():

    def __init__(self, xx):

        self.__x = xx

    @property

    def x(self):

        return self.__x

    @x.setter

    def x(self, xx):

        raise Exception("Attempt to change an immutable field")

我可以防止诸如此类的更改:


c = C([1,2,3])

c.x = [3,2,1]

但是我怎样才能防止这样的变化呢?


c.x.append(4)


慕桂英3389331
浏览 294回答 2
2回答

眼眸繁星

归根结底,您无法保护您的对象免受检查和操纵。另外,总是问自己“究竟来自谁?” 当您想“保护”数据时。有时,围绕不阅读文档的用户编写代码是不值得的。话虽如此,你可以考虑return tuple(self.__x)在吸气剂中。另一方面,如果__x包含其他可变对象,则不会阻止用户操作这些内部对象。(return list(self.__x)也将返回数据的浅拷贝,但隐含的“嘿,我应该是不可变的!”信号。)您绝对应该考虑的是在方法中更改self.__x = xx为,以便用户执行self.__x = list(xx)__init__var = [] c = C(var)不能“轻松”(或错误地,同样,可能存在可变的内部对象)c通过 mutating改变 的状态var。

皈依舞

最简单的方法是接受一个可迭代对象__init__并在内部将其转换为元组:class C(object):    def __init__(self, iterable):        self._tuple = tuple(iterable)    @property    def x(self):        return self._tuple    @x.setter    def x(self, value):      raise RuntimeError('can\'t reset the x attribute.')c = C([1, 2, 3])# c.x = 'a' Will raise 'RuntimeError: can't reset the x attribute.'print(c.x)像这样的设计使从类实例化的任何对象都是不可变的,因此变异操作应该返回新对象而不是更改当前对象的状态。例如,假设您要实现一个函数,该函数使 中的每个项目递增 1 self.x。使用这种方法,您需要编写类似于以下内容的内容:def increment_by_one(c):  return C(t+1 for t in c.x)由于创建和销毁对象会产生相关成本x,因此应根据您的用例评估此方法(防止属性突变)与 @timgeb 建议的方法之间的权衡。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python