<snip> > I think the basic misunderstandings are that > > (1) the __get__() method has to be implemented by the descriptor class > (2) the descriptor instances should be attributes of the class that is > supposed to invoke __get__(). E. g.: > > class C(object): > x = decriptor() > > c = C() > > c.x # invoke c.x.__get__(c, C) under the hood.
Exactly right, that was indeed my misunderstanding! I was thinking about __get__ and __set__ in the same terms as e.g. __getitem__ and __setitem__ > As a consequence you need one class per set of attributes, instantiating the > same AttrAccess for csv files with differing layouts won't work. That is no problem at all for me. One instance per file will be fine. > Here's how to do it all by yourself: > > class ReadColumn(object): > def __init__(self, index): > self._index = index > def __get__(self, obj, type=None): > return obj._row[self._index] > def __set__(self, obj, value): > raise AttributeError("oops") This appears to return one value, whereas I wanted I wanted to return all values of a column, ie as many values as there are rows. But the logic probably won't change. Same applies to the use of namedtuple, I suppose (?). I have never used namedtuple like namedtuple("Column", self.header)(*self.columns). > def first_row(instream): > reader = csv.reader(instream, delimiter=";") > > class Row(object): > def __init__(self, row): > self._row = row > > for i, header in enumerate(next(reader)): > setattr(Row, header, ReadColumn(i)) > > return Row(next(reader)) > > > f = StringIO("a;b;c\n1;2;3\n4;5;6\n7;8;9\n") > row = first_row(f) > print row.a > row.a = 42 > > Instead of a custom descriptor you can of course use the built-in property: > > for i, header in enumerate(next(reader)): > setattr(Row, header, property(lambda self, i=i: self._row[i])) This seems most attractive/straightforward to me. > In many cases you don't care about the specifics of the row class and use > collections.namedtuple: > > > def rows(instream): > reader = csv.reader(instream, delimiter=";") > Row = collections.namedtuple("Row", next(reader)) > return itertools.imap(Row._make, reader) > > > f = StringIO("a;b;c\n1;2;3\n4;5;6\n7;8;9\n") > row = next(rows(f)) > print row.a > row.a = 42 Thanks a lot for helping me! _______________________________________________ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor