[EMAIL PROTECTED] wrote: > I have what in my eyes seems a challenging problem. > Thanks to Peter Otten, i got the following code to work. It is a sort > of named tuple.
Don't trust code posted in a newsgroup -- it may sometimes be quality-challenged :-) > Now my problem is the following. I want to write a function called > createDerivedTuple in order to create a class derived from the one > created with the function createTuple, taking the parent class as first > argument: > def createDerivedTuple(parentclass,*names): > ....... code yet to be figured out .... > > The usage should be as follows: > > DerivedPoint=makeDerivedTuple(Point,'z') > p=DerivedPoint(4,7,9) > assert p.x==p[0] > assert p.y==p[1] > assert p.z==p[2] > assert DerivedPoint.x==0 > assert DerivedPoint.y==1 > assert DerivedPoint.z==2 > > I am still a newbie on metaclasses but i am convinced there are elegant > solutions to this challenging problem. Hey, if you don't try to solve it yourself we'll end up with me learning more than you... I didn't find a way to extend the approach with a per-class metaclass to support inheritance. I think you would have to subclass both class and metaclass. So I had to start all over again: class IndexProperty(object): def __init__(self, index): self.index = index def __get__(self, inst, cls): index = self.index if inst is None: return index return inst[index] class TupleType(type): def __new__(mcl, name, bases, classdict): names = classdict.get("_names") if names is not None: for base in bases: base_names = getattr(base, "_names", None) if base_names is not None: offset = len(base_names) break else: offset = 0 for i, n in enumerate(names): classdict[n] = IndexProperty(offset + i) if offset: names[:0] = base_names return type.__new__(mcl, name, bases, classdict) class Tuple(tuple): __metaclass__ = TupleType def __new__(cls, values): self = tuple.__new__(cls, values) if len(self) != len(cls._names): raise TypeError return self import unittest class P2(Tuple): _names = ["x", "y"] class P3(P2): _names = ["z"] def yield_them(seq): """Helper to ensure the implementation cannot rely on len().""" for item in seq: yield item class Test(unittest.TestCase): def test_P2(self): self.assertEquals(P2.x, 0) self.assertEquals(P2.y, 1) self.assertRaises(AttributeError, lambda: P2.z) def test_P3(self): self.assertEquals(P3.x, 0) self.assertEquals(P3.y, 1) self.assertEquals(P3.z, 2) def test_P2_inst(self): self.assertRaises(TypeError, P2, yield_them("A")) self.assertRaises(TypeError, P2, yield_them("ABC")) p = P2(yield_them("AB")) self.assertEquals(p.x, "A") self.assertEquals(p.y, "B") self.assertRaises(AttributeError, lambda: p.z) def test_P3_inst(self): self.assertRaises(TypeError, P3, yield_them("A")) self.assertRaises(TypeError, P3, yield_them("ABCD")) p = P3(yield_them("ABC")) self.assertEquals(p.x, "A") self.assertEquals(p.y, "B") self.assertEquals(p.z, "C") self.assertRaises(AttributeError, lambda: p.t) if __name__ == "__main__": unittest.main() I did not perform any tests other than the unittest given above. Peter -- http://mail.python.org/mailman/listinfo/python-list