虽然我从来不需要这个,但让我感到震惊的是,在 Python 中创建一个不可变对象(immutable对象)可能有点棘手。你不能只覆盖 __setattr__
, 因为那样你甚至不能在 __init__
中设置属性.对元组进行子类化是一种有效的技巧:
class Immutable(tuple):
def __new__(cls, a, b):
return tuple.__new__(cls, (a, b))
@property
def a(self):
return self[0]
@property
def b(self):
return self[1]
def __str__(self):
return "<Immutable {0}, {1}>".format(self.a, self.b)
def __setattr__(self, *ignored):
raise NotImplementedError
def __delattr__(self, *ignored):
raise NotImplementedError
但是你可以通过 self[0]
和 self[1]访问
,这很烦人。a
和 b
变量
这在纯 Python 中可行吗?如果没有,我将如何使用 C 扩展来做到这一点?
(仅适用于 Python 3 的答案是可以接受的)。
更新:
从 Python 3.7 开始,要走的路是使用 @dataclass
装饰者,请参阅新接受的答案。
最佳答案
我刚刚想到的另一个解决方案:获得与原始代码相同的行为的最简单方法是
Immutable = collections.namedtuple("Immutable", ["a", "b"])
它并没有解决属性可以通过[0]
等访问的问题,但至少它相当短并且提供了与pickle
兼容的额外优势> 和 复制
。
namedtuple
创建一个类似于我在 this answer 中描述的类型,即从 tuple
派生并使用 __slots__
。它在 Python 2.6 或更高版本中可用。
https://stackoverflow.com/questions/4828080/