在 Python 中使类不可变的方法
我正在做一些分布式计算,其中多台机器在假设它们都具有不同类的相同版本的情况下进行通信。因此,使这些类不可变似乎是一个很好的设计;并不是说它必须阻止恶意用户,而是足够不可变,永远不会被意外修改。
我该怎么办呢?例如,我将如何实现一个元类,使使用它的类在定义后不可变?
>>> class A(object):
... __metaclass__ = ImmutableMetaclass
>>> A.something = SomethingElse # Don't want this
>>> a = A()
>>> a.something = Whatever # obviously, this is still perfectly fine.
替代方法也很好,例如采用类并返回不可变类的装饰器/函数。
I'm doing some distributed computing in which several machines communicate under the assumption that they all have identical versions of various classes. Thus, it seems to be good design to make these classes immutable; not in the sense that it must thwart a user with bad intentions, just immutable enough that it is never modified by accident.
How would I go about this? For example, how would I implement a metaclass that makes the class using it immutable after it's definition?
>>> class A(object):
... __metaclass__ = ImmutableMetaclass
>>> A.something = SomethingElse # Don't want this
>>> a = A()
>>> a.something = Whatever # obviously, this is still perfectly fine.
Alternate methods is also fine, such as a decorator/function that takes a class and returns an immutable class.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
如果使用
__slots__
的老技巧确实有效不适合你,这个或其某些变体可以这样做:只需编写
__setattr__
方法你的元类是你的守卫。在此示例中,我阻止分配新属性,但允许修改现有属性:If the old trick of using
__slots__
does not fit you, this, or some variant of thereof can do:simply write the
__setattr__
method of your metaclass to be your guard. In this example, I prevent new attributes of being assigned, but allow modification of existing ones:不要在不可变的类上浪费时间。
您可以做的一些事情比尝试创建不可变对象要简单得多。
这里有五种单独的技术。您可以从其中挑选。任何一个都可以工作。有些组合也能发挥作用。
文档。事实上,他们不会忘记这一点。给予他们信任。
单元测试。使用处理
__setattr__
作为例外。对对象状态的任何更改都会导致单元测试失败。它很简单,不需要任何复杂的编程。
重写
__setattr__
以在每次尝试写入时引发异常。collections.namedtuple
。它们开箱即用,是不可变的。collections.Mapping
。它是不可变的,但您确实需要实现一些方法才能使其工作。Don't waste time on immutable classes.
There are things you can do that are far, far simpler than messing around with trying to create an immutable object.
Here are five separate techniques. You can pick and choose from among them. Any one will work. Some combinations will work, also.
Documentation. Actually, they won't forget this. Give them credit.
Unit test. Mock your application objects with a simple mock that handles
__setattr__
as an exception. Any change to the state of the object is a fail in the unit test. It's easy and doesn't require any elaborate programming.Override
__setattr__
to raise an exception on every attempted write.collections.namedtuple
. They're immutable out of the box.collections.Mapping
. It's immutable, but you do need to implement a few methods to make it work.归档不变性的主要方法:
tuple
、frozenset
、@dataclass(frozen=True) 装饰器,
BaseModel
和Config
覆盖:The main approaches for archive immutability:
tuple
,frozenset
,@dataclass(frozen=True)
decorator,BaseModel
withConfig
overriding:如果您不介意重复使用别人的工作:
http://packages.python.org/pysistence/
不可变的持久性(在功能上,不写入桌面意义上)数据结构。
即使您不按原样使用它们,源代码也应该提供一些灵感。例如,他们的 Expando 类在其构造函数中接受一个对象并返回它的不可变版本。
If you don't mind reusing someone else's work:
http://packages.python.org/pysistence/
Immutable persistent (in the functional, not write to desk sense) data structures.
Even if you don't use them as is, the source code should provide some inspiration. Their expando class, for example, takes an object in it's constructor and returns an immutable version of it.