Notice that I've used 'fromPairs' rather than 'fromMapping', since consistent order matters for a tuple. Comparison semantics are inherited directly from tuple, and don't care about names (they're only interested in values).
Also, it seems like there has to be a better way to do the "opposite of zip()" in fromPairs(), but I sure as hell can't think of it.
Cheers, Nick.
>>> a = named_tuple(['x', 'y'], (3, 8)) >>> a named_tuple(['x', 'y'], (3, 8)) >>> a.x 3 >>> a.y 8 >>> str(a) '(3, 8)' >>> b = named_tuple.fromPairs(sorted({'x':3, 'y':8}.items())) >>> b named_tuple(['x', 'y'], (3, 8)) >>> b.x 3 >>> b.y 8 >>> str(b) '(3, 8)' >>> a == b True >>>
And the code for the above:
class named_tuple(tuple): def __new__(cls, names, *args): self = tuple.__new__(cls, *args) self._names = dict(zip(names, range(len(names)))) return self
@staticmethod def fromPairs(items): names = [x[0] for x in items] values = [x[1] for x in items] return named_tuple(names, values)
def __getattr__(self, attr): if attr in self._names: return self[self._names[attr]] else: return tuple.__getattr__(attr)
def __repr__(self): return "named_tuple(%s, %s)" % (str(self.names()), str(tuple.__repr__(self)))
def __str__(self): return tuple.__repr__(self)
def names(self): return sorted(self._names.keys(), key=self._names.__getitem__) -- http://mail.python.org/mailman/listinfo/python-list