Как реализовать ленивую нагрузку атрибутов объекта, то есть, если доступ к атрибутам отсутствует, но еще не существует, вызывается какой-то метод объекта, который должен их загрузить?Lazy loading атрибутов
Моя первая попытка
def lazyload(cls):
def _getattr(obj, attr):
if "_loaded" not in obj.__dict__:
obj._loaded=True
try:
obj.load()
except Exception as e:
raise Exception("Load method failed when trying to access attribute '{}' of object\n{}".format(attr, e))
if attr not in obj.__dict__:
AttributeError("No attribute '{}' in '{}' (after loading)".format(attr, type(obj))) # TODO: infinite recursion if obj fails
return getattr(obj, attr)
else:
raise AttributeError("No attribute '{}' in '{}' (already loaded)".format(attr, type(obj)))
cls.__getattr__=_getattr
return cls
@lazyload
class Test:
def load(self):
self.x=1
t=Test() # not loaded yet
print(t.x) # will load as x isnt known yet
Сделаю LazyLoad только применительно к определенным именам атрибутов. Как я еще не сделал много метаклассирования, я не уверен, что это правильный подход. Что бы вы предложили?
* "Метаклассы глубже магии, чем 99% пользователей никогда не должны беспокоиться о том случае, если вам интересно, нужно ли вам их, вы не знаете.. " - TP *. Я думаю, что свойство, предложенное Даниэлем, было бы лучше. –
Я использую этот рецепт http://code.activestate.com/recipes/576563-cached-property/ – reclosedev
@Rik: Я не думаю, нужны ли мне метаклассы, а как решить проблему с lazyload. Пример Daniels еще не совсем решает его, поскольку он доступен только для чтения, и я не хочу дублировать строки кода для каждого события. Можно ли отрегулировать? – Gerenuk