class NamedTuple( tuple ): def __new__( cls, names ): return NamedTuple.Spawn( names ) def __getattr__( self, name ): try: return tuple.__getitem__( self, tuple.__getattribute__( self, '_names' )[name] ) except KeyError: raise AttributeError, "object has no attribute named '%s'" % name except AttributeError: raise RuntimeError, "'NamedTuple' class cannot be used directly, use subclass generated by Spawn instead" def __setattr__( self, name, value ): raise TypeError, "'NamedTuple' object has only read-only attributes (assign to .%s)" % name def Spawn( names ): class __temp( NamedTuple ): def __new__( cls, values ): return tuple.__new__( cls, values ) __temp._names = dict( zip( names, range( len( names ) ))) return __temp Spawn = staticmethod( Spawn ) if __name__ == '__main__': # There are two ways to Spawn a tuple class: Employee = NamedTuple.Spawn(['first', 'last', 'id']) Product = NamedTuple(['name', 'cost', 'profit', 'qty']) emp1 = Employee(['Jane', 'Foo', 1]) # The number of values is not limited to the number of # named attributes defined. emp2 = Employee(['John', 'Bar', 2, 'What about this?']) print emp1, emp1.last, emp1[2] print emp2, emp2.first, emp2[3] pro1 = Product(['Box', .10, .05, 100]) print pro1, pro1.profit, pro1[0]