已經尋找一種方式來強制執行自定義類型的不變性,而不是自定義類型的不可改變的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