我想使用类似collections.namedtuple
的东西,它可以很好地强制实现不变性并促进一个简单的值类,但它不允许子类化;例如,我想做类似以下to add extra read-only properties的事情:
from collections import namedtuple
class Foo(namedtuple('Foo','foo')):
@property
def antifoo(self):
return -self.foo
class Bar(Foo):
""" ARGH: somehow we add a 'bar' field """
@property
def inversebar(self):
return 1.0/bar
唯一的问题是没有添加其他属性的机制。所以我查看了collections.namedtuple('Test','foo bar baz', verbose=True)
的结果,并根据自己的目的进行了调整:
from collections import OrderedDict
from operator import itemgetter as _itemgetter
class Foo(tuple):
__slots__ = ()
_fields = ('foo',)
_nargs = 1
_repr_format = '(foo=%r)'
foo = property(_itemgetter(0), doc='Alias for field number 0')
def __new__(_cls, foo):
return tuple.__new__(_cls, (foo,))
@classmethod
def _make(cls, iterable, new=tuple.__new__, len=len):
'Make a new Foo object from a sequence or iterable'
result = new(cls, iterable)
if len(result) != cls._nargs:
raise TypeError('Expected 1 argument, got %d' % len(result))
return result
def _replace(self, **kwds):
'Return a new {typename} object replacing specified fields with new values'
result = self._make(map(kwds.pop, self._fields, self))
if kwds:
raise ValueError('Got unexpected field names: %r' % kwds.keys())
return result
def __repr__(self):
'Return a nicely formatted representation string'
return self.__class__.__name__ + self._repr_format % self
def _asdict(self):
'Return a new OrderedDict which maps field names to their values.'
return OrderedDict(zip(self._fields, self))
__dict__ = property(_asdict)
def __getstate__(self):
'Exclude the OrderedDict from pickling'
pass
@property
def antifoo(self):
return -self.foo
class Bar(Foo):
_fields = ('foo','bar')
_nargs = 2
_repr_format = '(foo=%r, bar=%r)'
bar = property(_itemgetter(1), doc='Alias for field number 1')
def __new__(_cls, foo, bar):
return tuple.__new__(_cls, (foo, bar))
@property
def inversebar(self):
return 1.0/self.bar
这个似乎正常工作,但是没关系,还是我犯了一个严重的错误?