I have a class WeightedArc defined as follows:
class Arc(tuple):
@property
def tail(self):
return self[0]
@property
def head(self):
return self[1]
@property
def inverted(self):
return Arc((self.head, self.tail))
def __eq__(self, other):
return self.head == other.head and self.tail == other.tail
class WeightedArc(Arc):
def __new__(cls, arc, weight):
self.weight = weight
return super(Arc, cls).__new__(arc)
This code clearly doesn't work, because self
isn't defined for WeightArc.__new__
. How do I assign the attribute weight to the WeightArc class?
The fixed-up version of your original code is:
class WeightedArc(Arc):
def __new__(cls, arc, weight):
self = tuple.__new__(cls, arc)
self.weight = weight
return self
Another approach to look at the verbose option for collections.namedtuple to see an example of how to subclass tuple:
>>> from collections import namedtuple, OrderedDict
>>> _property = property
>>> from operator import itemgetter as _itemgetter
>>> Arc = namedtuple('Arc', ['head', 'tail'], verbose=True)
class Arc(tuple):
'Arc(head, tail)'
__slots__ = ()
_fields = ('head', 'tail')
def __new__(_cls, head, tail):
'Create new instance of Arc(head, tail)'
return _tuple.__new__(_cls, (head, tail))
@classmethod
def _make(cls, iterable, new=tuple.__new__, len=len):
'Make a new Arc object from a sequence or iterable'
result = new(cls, iterable)
if len(result) != 2:
raise TypeError('Expected 2 arguments, got %d' % len(result))
return result
def __repr__(self):
'Return a nicely formatted representation string'
return 'Arc(head=%r, tail=%r)' % self
def _asdict(self):
'Return a new OrderedDict which maps field names to their values'
return OrderedDict(zip(self._fields, self))
def _replace(_self, **kwds):
'Return a new Arc object replacing specified fields with new values'
result = _self._make(map(kwds.pop, ('head', 'tail'), _self))
if kwds:
raise ValueError('Got unexpected field names: %r' % kwds.keys())
return result
def __getnewargs__(self):
'Return self as a plain tuple. Used by copy and pickle.'
return tuple(self)
head = _property(_itemgetter(0), doc='Alias for field number 0')
tail = _property(_itemgetter(1), doc='Alias for field number 1')
You can cut, paste, and modify this code, or just subclass from it as shown in the namedtuple docs.
To extend this class, build off of the fields in Arc:
WeightedArc = namedtuple('WeightedArc', Arc._fields + ('weight',))
Another approach to look at the verbose option for collections.namedtuple to see an example of how to subclass tuple
Better yet, why not use namedtuple ourselves? :)
class Arc(object):
def inverted(self):
d = self._asdict()
d['head'], d['tail'] = d['tail'], d['head']
return self.__class__(**d)
class SimpleArc(Arc, namedtuple("SimpleArc", "head tail")): pass
class WeightedArc(Arc, namedtuple("WeightedArc", "head tail weight")): pass
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With