How would you implement lazy load of object attributes, i.e. if attributes are accessed but don't exist yet, some object method is called which is supposed to load these?
My first attempt is
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
I will make lazyload specific to certain attribute names only. As I havent done much meta-classing yet, I'm not sure if that is the right approach. What would you suggest?
Seems like a simple property
would do the trick better:
@property
def my_attribute():
if not hasattr(self, '_my_attribute'):
do_expensive_operation_to_get_attribute()
return self._my_attribute
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With