动态惰性 class 属性 python
Dynamic lazy class properties python
我有一个class,记录,用来包含读取文本文件的结果。该文件包含一个带有字段和标签的简单数据库。我想让每个 Record 实例只具有与其数据库关联的属性。基本上:
R1 = Record("file1")
R2 = Record("file2")
print(R1.TI) #"Record 1's title"
print(R2.TI) #AttributeError: 'Record' object has no attribute 'TI'
不幸的是,某些字段可能需要大量处理才能 return 一些有用的东西,并且可能永远不需要这些值。所以我希望在第一次调用它们时确定该值,而不是在初始化对象时确定。
因为我只知道标签名称,所以我尝试过:
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))
这导致 R1.TI
生成包装器对象而不是我想要的值。所以我怀疑我用 get 方法搞砸了。
注意: 我正在尝试使属性成为单个 class 实例的一部分 和 在需要时才进行评估。我可以实施一个或另一个,但无法确定如何同时执行这两个操作。
您正在实现描述符协议,并且描述符属于 class 而不是 class 的实例,因此您不能将其分配给实例属性。
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')
我有一个似乎可行的解决方案,虽然它很丑陋:
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__
但这似乎可行。
我有一个class,记录,用来包含读取文本文件的结果。该文件包含一个带有字段和标签的简单数据库。我想让每个 Record 实例只具有与其数据库关联的属性。基本上:
R1 = Record("file1")
R2 = Record("file2")
print(R1.TI) #"Record 1's title"
print(R2.TI) #AttributeError: 'Record' object has no attribute 'TI'
不幸的是,某些字段可能需要大量处理才能 return 一些有用的东西,并且可能永远不需要这些值。所以我希望在第一次调用它们时确定该值,而不是在初始化对象时确定。
因为我只知道标签名称,所以我尝试过:
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))
这导致 R1.TI
生成包装器对象而不是我想要的值。所以我怀疑我用 get 方法搞砸了。
注意: 我正在尝试使属性成为单个 class 实例的一部分 和 在需要时才进行评估。我可以实施一个或另一个,但无法确定如何同时执行这两个操作。
您正在实现描述符协议,并且描述符属于 class 而不是 class 的实例,因此您不能将其分配给实例属性。
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')
我有一个似乎可行的解决方案,虽然它很丑陋:
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__
但这似乎可行。