我有一个类Record,用于包含读取文本文件的结果。该文件包含一个包含字段和标记的简单数据库。我想让每个Record实例只有与其数据库关联的属性。基本上:
lessc -x style.less style.min.css
遗憾的是,某些字段可能需要大量处理才能返回有用的内容,并且可能永远不需要这些值。所以我希望在初始化对象时第一次调用它时确定值。
因为我知道标签名称只是我尝试过:
R1 = Record("file1")
R2 = Record("file2")
print(R1.TI) #"Record 1's title"
print(R2.TI) #AttributeError: 'Record' object has no attribute 'TI'
这会导致 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))
生成包装器对象而不是我想要的值。所以我怀疑我用get方法搞砸了什么。
注意:我正在尝试使各个类实例的属性和在需要之前不进行评估。我可以实现其中一个,但无法确定如何做到这两个。
答案 0 :(得分:0)
您正在实现描述符协议,并且描述符属于类而不是类的实例,因此您无法将其分配给实例属性。
class Tag(object):
def __init__(self, tag):
self.tag = tag
self.data = None
def __get__(self, instance, owner):
if not instance: # if accessed with the class directly, ie. Record.T1, just return this descriptor
return self
if self.data is None:
print "Reading data"
self.data = range(10)
return self.data
class Record(object):
T1 = Tag('T1')
答案 1 :(得分:0)
我有一个似乎有效的解决方案,虽然它很难看:
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)
我不喜欢覆盖__getattribute__
,但这似乎有效。