3
我在我的一个类建模json数据中有许多类似的字段。所有字段初始化为无,以帮助静态工具知道它们存在,然后帮助函数帮助基于他们正在建模的一块json数据对它们进行初始化(如果您想知道,请参考The SecondHandSongs API)。有没有更好的方法来为动态命名属性做一个getter属性?
某些数据只会检索您必须提取的额外数据的URI。所以我想使用将隐藏变量初始化为None并在首次请求时获取/解码数据的旧技巧。但setattr(self.__class__)
看起来很丑。
有没有更好的方法来做(在python中动态设置属性)?
def _initialize_url_fields(self, attrNamesToFactoryFunction, json_data):
for (name, factoryFunction) in attrNamesToFactoryFunction.iteritems():
try:
url = json_data[name]
except KeyError:
continue
setattr(self, name + "_url", url)
setattr(self, "_" + name, None)
setattr(self.__class__, name, property(lambda s: s._getter("_" + name, url, factoryFunction)))
def _getter(self, hidden_prop_name, url, factoryFunction):
if not getattr(self, hidden_prop_name):
json_data = SHSDataAcess.getSHSData(url)
setattr(self, hidden_prop_name, factoryFunction(json_data))
return getattr(self, hidden_prop_name)
编辑: 我刚刚意识到我试图从称为实例方法初始化 设置属性。可以预料,它第二次失败了。
编辑2:
这里的意识到我设置每个对象的属性(不可能的,如果没有一个单独的类)
class ShsData(object):
def _initialize_url_fields(self, attrNamesToFactoryFunctions, json_data):
for (name, factoryFunction) in attrNamesToFactoryFunctions.items():
self._getter_factory_functions[name] = factoryFunction
uri = None
try:
uri = json_data[name]
except KeyError:
pass
setattr(self, name + "_uri", uri)
setattr(self, "_" + name, None)
def _fetch_shs_data_on_first_access_getter(base_prop_name):
def getter(self):
factoryFunction = self._getter_factory_functions[base_prop_name]
hidden_prop_name = "_" + base_prop_name
uri_prop_name = base_prop_name + "_uri"
if not getattr(self, hidden_prop_name):
if getattr(self, uri_prop_name):
json_data = SHSDataAcess.getSHSData(getattr(self, uri_prop_name))
setattr(self, hidden_prop_name, factoryFunction(json_data))
else:
return None
return getattr(self, hidden_prop_name)
return getter
class ShsArtist(ShsData):
performances_data = property(_fetch_shs_data_on_first_access_getter("performances"))
creditedWorks_data = property(_fetch_shs_data_on_first_access_getter("creditedWorks"))
releases_data = property(_fetch_shs_data_on_first_access_getter("releases"))
def __init__(self, json_data):
...
self._initialize_url_fields({"performances": lambda xs: [ShsPerformance(x) for x in xs],
"creditedWorks": lambda xs: [ShsWork(x) for x in xs],
"releases": lambda xs: [ShsRelease(x) for x in xs]},
json_data)
另一种方法是使用自定义的'__getattr__',但不会我会说更漂亮一点。 –
属性有什么问题:http://docs.python.org/howto/descriptor.html。我相信你可以使用缓存修饰器来构建它。 – Marcin
@Marcin:请注意,OP已经在使用属性,动态分配它们。 –