为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

慕桂英3389331 2021-08-24 18:16:09
例如,我有一个带有字段的类__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)
查看完整描述

2 回答

?
眼眸繁星

TA贡献1873条经验 获得超9个赞

归根结底,您无法保护您的对象免受检查和操纵。另外,总是问自己“究竟来自谁?” 当您想“保护”数据时。

有时,围绕不阅读文档的用户编写代码是不值得的。

话虽如此,你可以考虑return tuple(self.__x)在吸气剂中。另一方面,如果__x包含其他可变对象,则不会阻止用户操作这些内部对象。(return list(self.__x)也将返回数据的浅拷贝,但隐含的“嘿,我应该是不可变的!”信号。)

您绝对应该考虑的是在方法中更改self.__x = xx为,以便用户执行self.__x = list(xx)__init__

var = []
c = C(var)

不能“轻松”(或错误地,同样,可能存在可变的内部对象)c通过 mutating改变 的状态var


查看完整回答
反对 回复 2021-08-24
?
皈依舞

TA贡献1851条经验 获得超3个赞

最简单的方法是接受一个可迭代对象__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 建议的方法之间的权衡。


查看完整回答
反对 回复 2021-08-24
  • 2 回答
  • 0 关注
  • 207 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信