【问题标题】:How to make class immutable in python? [duplicate]如何在python中使类不可变? [复制]
【发布时间】:2014-03-20 20:42:01
【问题描述】:

我在这里阅读了很多关于这个主题的内容,但我仍然找不到合适的答案。 我有一个像这样的课程:

class A(object):

    def __init__(self, first, second):
        self.first = first
        self.second = second

    def __eq__(self, other):
        return ****

    def __str__(self):
        return *****

    def __repr__(self):
        return **** 

a = A("a", "b")

例如,我如何禁止 a.first = "c" ?

【问题讨论】:

  • 我认为这就是您正在寻找的答案 - stackoverflow.com/questions/4828080/… :)
  • 这是我读到的第一个想法,但我仍然无法将它应用到我的案例中。这就是我发布代码的原因。不过还是谢谢。

标签: python class immutability


【解决方案1】:

您可以覆盖__setattr__ 以防止任何更改:

def __setattr__(self, name, value):
    raise AttributeError('''Can't set attribute "{0}"'''.format(name))

或阻止添加新属性:

def __setattr__(self, name, value):
    if not hasattr(self, name):
        raise AttributeError('''Can't set attribute "{0}"'''.format(name))
    # Or whatever the base class is, if not object.
    # You can use super(), if appropriate.
    object.__setattr__(self, name, value)

您还可以将hasattr 替换为检查允许的属性列表:

if name not in list_of_allowed_attributes_to_change:
    raise AttributeError('''Can't set attribute "{0}"'''.format(name))

另一种方法是使用属性而不是普通属性:

class A(object):

    def __init__(self, first, second):
        self._first = first
        self._second = second

    @property
    def first(self):
        return self._first

    @property
    def second(self):
        return self._second

【讨论】:

  • 好的,我怎样才能引发“AttributeError: can't set attribute”,例如使用 setattr
  • 编辑引发异常而不是什么都不做。
  • @user253956 不幸的是,覆盖__setattr__ 会阻止您在__init__ 中设置属性。你需要更复杂的东西。
  • 是的,我之前遇到过这个问题。另一方面,@property 工作得很好。
【解决方案2】:

您可以在初始化对象的最后一步禁用__setattr__

class A(object):

    def __init__(self, first, second):
        self.first = first
        self.second = second
        self.frozen = True

    def __setattr__(self, name, value):
        if getattr(self, 'frozen', False):
            raise AttributeError('Attempt to modify immutable object')
        super(A, self).__setattr__(name, value)

>>> a = A(1, 2)
>>> a.first, a.second
(1, 2)
>>> a.first = 3

Traceback (most recent call last):
  File "<pyshell#46>", line 1, in <module>
    a.first = 3
  File "<pyshell#41>", line 10, in __setattr__
    raise AttributeError('Attempt to modify immutable object')
AttributeError: Attempt to modify immutable object

编辑: 这个答案有一个缺陷,我敢肯定所有其他解决方案都有这个缺陷:如果成员本身是可变的,则没有任何东西可以保护它们。例如,如果您的对象包含一个列表,则一切都结束了。这与在 C++ 中声明对象 const 递归地扩展到其所有成员形成对比。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-03-24
    • 2017-11-23
    • 2012-01-04
    • 1970-01-01
    • 2015-01-23
    • 1970-01-01
    • 2011-06-27
    相关资源
    最近更新 更多