I have a class, Record, that is used to contain the results of reading text file. The file contains a simple database with fields and tags. I would like to have each Record instance only have the properties associated with its database. Basically:
R1 = Record("file1")
R2 = Record("file2")
print(R1.TI) #"Record 1's title"
print(R2.TI) #AttributeError: 'Record' object has no attribute 'TI'
unfortunately some of the fields may require a large amount of processing to return something useful, and those values may never be needed. So I would like the value to be determined the first time they are called not when the object is initialized.
Because I know the tags name's only I have tried:
class tagWrapper(object):
def __init__(self, tag):
self.tag = tag
self.data = None
def __get__(self, instance, owner):
if self.data == None:
try:
#tagToFunc is a dictionary that maps tags to their processing function
self.data = tagToFunc[self.tag](instance._rawDataDict[self.tag])
except KeyError: #I do not know the full list of tags
self.data = instance._rawDataDict[self.tag]
return self.data
class Record(object):
def __init__(self, file):
#Reading file and making _rawDataDict
setattr(self, tag, tagWrapper(tag))
This causes R1.TI
to produce the wrapper object not the value I want. So I suspect I am screwing something up with the get method.
Note: I am trying to make the attributes part of the individual class instances and not evaluated until needed. I can implement one or the other but have not been able to determine how to do both.
I have a solution that seems to work although it is quite ugly:
class Record(object):
def __init__(self, file):
self._unComputedTags = set() #needs to be initialized first
#stuff
self._unComputedTags = set(self._fieldDict.keys())
for tag in self._fieldDict:
self.__dict__[tag] = None
def __getattribute__(self, name):
if name == '_unComputedTags':
#This may be unnecessary if I play with things a bit
return object.__getattribute__(self, '_unComputedTags')
if name in self._unComputedTags:
try:
tagVal = tagToFunc[name](self._fieldDict[name])
except KeyError:
tagVal = self._fieldDict[name]
setattr(self, name, tagVal)
self._unComputedTags.remove(name)
return object.__getattribute__(self, name)
I do not like overwriting __getattribute__
but this seems to work.