在Python中使类不可变的方法

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (49)

我正在做一些分布式计算,其中几台机器在假设它们都有相同版本的不同类的情况下进行通信。因此,使这些类不可变似乎是一个很好的设计;而不是因为它必须阻止一个意图不良的用户,而只是不变的,不会被意外地修改。

我该怎么做?例如,我如何实现一个元类,使类在定义后使用它是不可变的?

>>> class A(object):
...     __metaclass__ = ImmutableMetaclass
>>> A.something = SomethingElse # Don't want this
>>> a = A()
>>> a.something = Whatever # obviously, this is still perfectly fine.

替代方法也很好,例如一个接受类并返回不可变类的修饰器/函数。

提问于
用户回答回答于

如果用旧的伎俩__slots__不适合您,这或其某些变体可以做到:只需编写__setattr__。在本例中,我防止分配新属性,但允许修改现有属性:

def immutable_meta(name, bases, dct):
    class Meta(type):
        def __init__(cls, name, bases, dct):
            type.__setattr__(cls,"attr",set(dct.keys()))
            type.__init__(cls, name, bases, dct)

        def __setattr__(cls, attr, value):
            if attr not in cls.attr:
                raise AttributeError ("Cannot assign attributes to this class")
            return type.__setattr__(cls, attr, value)
    return Meta(name, bases, dct)


class A:
    __metaclass__ = immutable_meta
    b = "test"

a = A()
a.c = 10 # this works
A.c = 20 # raises valueError
用户回答回答于

不要把时间浪费在不可变的课程上。

有些事情你可以做的远,远比试图创建一个不可变的对象简单得多。

这里有五种不同的技巧。你可以从中挑选。任何人都会成功的。一些组合也能工作。

  1. 文件。事实上,他们不会忘记的。给他们点信用。
  2. 单元测试。使用一个简单的模拟来模拟应用程序对象__setattr__作为例外。对对象状态的任何更改都是单元测试中的失败。这很简单,不需要任何精细的编程。
  3. 覆盖__setattr__若要对每次尝试写入引发异常,请执行以下操作。
  4. collections.namedtuple...。他们是一成不变的。
  5. collections.Mapping...。它是不可变的,但是您确实需要实现一些方法来使其工作。

扫码关注云+社区

领取腾讯云代金券