已经寻找一种方式来强制执行自定义类型的不变性,而不是自定义类型的不可改变的Python元类已经发现我用我自己的射击在一个解决方案中的一个元类的形式提出了一份满意的答卷:强制执行
class ImmutableTypeException(Exception): pass
class Immutable(type):
'''
Enforce some aspects of the immutability contract for new-style classes:
- attributes must not be created, modified or deleted after object construction
- immutable types must implement __eq__ and __hash__
'''
def __new__(meta, classname, bases, classDict):
instance = type.__new__(meta, classname, bases, classDict)
# Make sure __eq__ and __hash__ have been implemented by the immutable type.
# In the case of __hash__ also make sure the object default implementation has been overridden.
# TODO: the check for eq and hash functions could probably be done more directly and thus more efficiently
# (hasattr does not seem to traverse the type hierarchy)
if not '__eq__' in dir(instance):
raise ImmutableTypeException('Immutable types must implement __eq__.')
if not '__hash__' in dir(instance):
raise ImmutableTypeException('Immutable types must implement __hash__.')
if _methodFromObjectType(instance.__hash__):
raise ImmutableTypeException('Immutable types must override object.__hash__.')
instance.__setattr__ = _setattr
instance.__delattr__ = _delattr
return instance
def __call__(self, *args, **kwargs):
obj = type.__call__(self, *args, **kwargs)
obj.__immutable__ = True
return obj
def _setattr(self, attr, value):
if '__immutable__' in self.__dict__ and self.__immutable__:
raise AttributeError("'%s' must not be modified because '%s' is immutable" % (attr, self))
object.__setattr__(self, attr, value)
def _delattr(self, attr):
raise AttributeError("'%s' must not be deleted because '%s' is immutable" % (attr, self))
def _methodFromObjectType(method):
'''
Return True if the given method has been defined by object, False otherwise.
'''
try:
# TODO: Are we exploiting an implementation detail here? Find better solution!
return isinstance(method.__objclass__, object)
except:
return False
然而,虽然一般的方法似乎运作相当好还是有一些前途未卜的实施细则(另见代码TODO注释):
- 我如何检查是否有特定的方法已经在任何地方实现类型层次?
- 如何检查哪种类型是方法声明的来源(即作为已定义方法的哪个类型的一部分)?
为什么要强制执行不变性?它不是那么和谐吗? – nikow 2010-03-28 20:54:54
构建在类型中的Python也是不可变的。主要是为了帮助找出与错误地修改契约不可变对象有关的可能错误,我希望为自定义类型强制执行不变性,而这些类型一直是惯例不变的。 – 2010-03-29 06:44:07
我认为Python内置的类型通常是不可变的,其他原因。一个对象是不可变的合约看起来很直截了当。如果您已经需要元类来调试这样一个相对简单的方面,那么如果遇到真正的错误,您会怎么做?通过元类强制每一份合约? Python可能不适合此语言。 – nikow 2010-03-29 10:50:18