por*_*uod 16 python metaclass immutability
我正在做一些分布式计算,其中几台机器在假设它们都具有不同类的相同版本的情况下进行通信.因此,使这些类不可变是一种好的设计; 不是因为它必须挫败一个意图不好的用户,只是不可改变的,它永远不会被意外修改.
我该怎么做?例如,我如何实现一个元类,使得类在定义后使用它是不可变的?
>>> class A(object):
... __metaclass__ = ImmutableMetaclass
>>> A.something = SomethingElse # Don't want this
>>> a = A()
>>> a.something = Whatever # obviously, this is still perfectly fine.
Run Code Online (Sandbox Code Playgroud)
替代方法也很好,例如一个装饰器/函数,它接受一个类并返回一个不可变的类.
不要在不可变的类上浪费时间。
您可以做的一些事情比尝试创建不可变对象要简单得多。
这里有五种单独的技术。您可以从其中挑选。任何一个都可以工作。有些组合也能发挥作用。
文档。事实上,他们不会忘记这一点。给予他们信任。
单元测试。__setattr__使用作为异常处理的简单模拟来模拟您的应用程序对象。对对象状态的任何更改都会导致单元测试失败。它很简单,不需要任何复杂的编程。
重写__setattr__以在每次尝试写入时引发异常。
collections.namedtuple。它们开箱即用,是不可变的。
collections.Mapping。它是不可变的,但您确实需要实现一些方法才能使其工作。
如果旧的使用技巧__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
Run Code Online (Sandbox Code Playgroud)