[Tutor] question about descriptors

Albert-Jan Roskam sjeik_appie at hotmail.com
Sat Nov 7 07:53:11 EST 2015



p, li { white-space: pre-wrap; }

Hi,
First, before I forget, emails from hotmail/yahoo etc appear to end up in the spam folder these days, so apologies in advance if I do not appear to follow up to your replies.
Ok, now to my question. I want to create a class with read-only attribute access to the columns of a .csv file. E.g. when a file has a column named 'a', that column should be returned as list by using instance.a. At first I thought I could do this with the builtin 'property' class, but I am not sure how. I now tried to use descriptors (__get__ and __set__), which are also used by ' property' (See also: https://docs.python.org/2/howto/descriptor.html). 

In the " if __name__ == '__main__'" section, [a] is supposed to be a shorthand for == equivalent to [b]. But it's not.I suspect it has to do with the way attributes are looked up. So once an attribute has been found in self.__dict__ aka "the usual place", the search stops, and __get__ is never called. But I may be wrong. I find the __getatttribute__, __getattr__ and __get__ distinction quite confusing.
What is the best approach to do this? Ideally, the column values should only be retrieved when they are actually requested (the .csv could be big).
Thanks in advance!



import csv
from cStringIO import StringIO


class AttrAccess(object):


    def __init__(self, fileObj):
        self.__reader = csv.reader(fileObj, delimiter=";")
        self.__header = self.__reader.next()
        #[setattr(self, name, self.__get_column(name)) for name in self.header]
        self.a = range(10)


    @property
    def header(self):
        return self.__header
        
    def __get_column(self, name):
        return [record[self.header.index(name)] for record in self.__reader]  # generator expression might be better here.
        
    def __get__(self, obj, objtype=type):
        print "__get__ called"
        return self.__get_column(obj)
        #return getattr(self, obj)
        
    def __set__(self, obj, val):
        raise AttributeError("Can't set attribute")
        
if __name__ == " __main__":
    f = StringIO("a;b;c\n1;2;3\n4;5;6\n7;8;9\n")
    instance = AttrAccess(f)
    print instance.a  # [a] does not call __get__. Looks, and finds, in self.__dict__?
    print instance.__get__("a")  # [b] this is supposed to be equivalent to [a]
    instance.a = 42  # should throw AttributeError!



 		 	   		  


More information about the Tutor mailing list