On Wed, 21 May 2008 12:47:44 +0200, pataphor <[EMAIL PROTECTED]> wrote:
>On Tue, 20 May 2008 10:40:17 -0500 >"David C. Ullrich" <[EMAIL PROTECTED]> wrote: > >> > > Today's little joke: Long ago I would have solved >> > > this by storing the data as a list of rows and _also_ >> > > a list of columns, updating each one any time the >> > > other changed. Just goes to show you things >> > > could always be worse... >> > >> > Well have I ever ... I only thought about this last week and I >> > actually thought it was a *good* idea. >> >> Sorry. If you really want to do this you could keep things >> in sync automatically by writing the appropriate __setitem__ >> and resolving never to modify the data except through that... >> >> def whatever.__setitem__(self, (row,col), value): >> self.rows[row][col] = value >> self.cols[col][row] = value > >Using the trick of encapsulating the values inside single-element lists >one can make a transposition of the matrix and get synchronicity for >the little price of doubling the number of instances. Since the views >share the data this is a lot less expensive than one would think. One >can use the row view or the column view to alter data and the changes >will automatically be visible in the other view, since the views update >the same lists. Oh - that's different. This is not what I thought you had in mind (it's not what I had in mind in the thing I called a joke.) >There is a little notational gotcha, instead of writing >row[0] = [1,2,3] one now must write row[0][:] = [1,2,3] or else >synchronicity is lost. > >I found a nice ListMixin class at >http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/440656 > >Using that I wrote the following proof of concept: > >class Storage(ListMixin): > > def __init__(self, seq=[]): > self.L = [[x] for x in seq] > > def _constructor(self, iterable): > return Storage(iterable) Probably I'm just being dense. Why does _constructor exist? (Oh - looking at things below, I imagine it's something to do with ListMixin.) > def __len__(self): > return len(self.L) > > def _get_element(self, i): > assert 0 <= i < len(self) > return self.L[i][0] > > def _set_element(self, i, x): > assert 0 <= i < len(self) > self.L[i][0] = x > > def _resize_region(self, start, end, new_size): > assert 0 <= start <= len(self) > assert 0 <= end <= len(self) > assert start <= end > self.L[start:end] = [[None] for i in range(new_size)] > >def test(): > n = 3 > R = range(n) > it = iter(range(n*n)) > MR = [Storage(it.next() for i in R) for i in R] > MC = [Storage() for i in R] > T = zip(*[x.L for x in MR]) > for x,y in zip(MC,T): > x.L = y > print MR > print MC > MC[2][:] = 'abc' > print > print MR > print MC > >if __name__=='__main__': > test() > >Output: > >[Storage([0, 1, 2]), Storage([3, 4, 5]), Storage([6, 7, 8])] >[Storage([0, 3, 6]), Storage([1, 4, 7]), Storage([2, 5, 8])] > >[Storage([0, 1, 'a']), Storage([3, 4, 'b']), Storage([6, 7, 'c'])] >[Storage([0, 3, 6]), Storage([1, 4, 7]), Storage(['a', 'b', 'c'])] > >P. David C. Ullrich -- http://mail.python.org/mailman/listinfo/python-list