动态惰性类属性python

时间:2015-06-02 03:12:56

标签: python class oop properties

我有一个类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方法搞砸了什么。

注意:我正在尝试使各个类实例的属性在需要之前不进行评估。我可以实现其中一个,但无法确定如何做到这两个。

2 个答案:

答案 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__,但这似乎有效。