Having a hard time phrasing this in the form of a question... The other day I saw a thread where someone asked about overrideable properties and nobody offered the advice that properties are Bad. So maybe we've got over that. I suppose properties could have Bad consequences if a user doesn't know they exist and think that a certain property of an object is just an ordinary attribute. But that applies to almost any aspect of any language.
If a person comes from, say, Object Pascal (Delphi) then properties are hard to live without. The other day I decided I wanted what OP calls an "indexed property" or "array property". Couldn't figure out how to make a _property_ behave that way. So I read a little bit about descriptors, and a few minutes later I had an indexedproperty thing that works just like property, except it gives an indexed property! This is just too cool. Why? For example, a Matrix should have a row[n] property allowing things like m.row[0] = m.row[1] + m.row[2] Ok, you could do _that_ by just making row an ordinary list of Row objects. But then you'd have to say m.row[0] = Row([1,2,3]) where I want to be able to say m.row[0] = [1,2,3] and have the Row created automatically. _Also_ with these indexed properties my Matrix can have m.row[j] and m.col[k] that look exactly the same to a client - we don't want to store a list of rows internally and also store the same data in a list of columns. Too cool. Hmm, none of that's a valid excuse for a post here. Um, right, here we go: Anyone see problems or possible improvements with the implementation of indexedproperty below? """indexed.py: "indexedproperty" works more or less like "property" except it gives what in Object Pascal would be an "indexed property". See the __name__="__main__" section below for a demo """ class WriteOnlyIP(Exception): def __str__(self): return """ indexed property is write-only """ class ReadOnlyIP(Exception): def __str__(self): return """ indexed property is read-only """ class indexedproperty(object): def __init__(self, getitem=None, setitem=None): self.getitem = getitem self.setitem = setitem def __get__(self, obj, owner): self.obj = obj return self def __getitem__(self, index): if self.getitem: return self.getitem(self.obj, index) else: raise WriteOnlyIP def __setitem__(self, index, value): if self.setitem: self.setitem(self.obj, index, value) else: raise ReadOnlyIP if __name__ == "__main__": class AClass(object): def __init__(self): self.cells = [[0,0], [0,0]] def SetCell(self, (row, col), value): self.cells[row][col] = value def GetCell(self, (row, col)): return self.cells[row][col] cell = indexedproperty(GetCell, SetCell) C = AClass() for row in range(2): for col in range(2): C.cell[row, col] = "row: %s, col: %s" % (row, col) for row in range(2): for col in range(2): print C.cell[row, col] C.cell[0,0], C.cell[1,1] = C.cell[1,1], C.cell[0,0] print "After C.cell[0,0], C.cell[1,1] = C.cell[1,1], C.cell[0,0]:" for row in range(2): for col in range(2): print C.cell[row, col] -- David C. Ullrich -- http://mail.python.org/mailman/listinfo/python-list