The goal is to create a custom python class, that allows for lazyloading of attributes (a fairly common question here with a variety of different solutions) but that only runs the expensive initialization step once ON lazy access. Here's an example:
class LazyDateModule()
def __init__(self, args):
self.args = args
self._expensive_date_attr = None
def _expensive_init():
time.sleep(10)
self._expensive_date_attr = date.today()
@memoize
def date_str():
return str(self._expensive_date_attr)
@memoize
def month_num():
return self._expensive_date_attr.month
In this example, my @memoize decorator handles the caching step for me.
If I'm defining my LazyDateModule elsewhere:
LDM = LazyDateModule()
How do I run the _expensive_init() ONLY on the first time any of the memoized attribute methods were accessed? I've tried something like this:
class LazyDateModule()
def __init__(self, args):
self.args = args
self._assembled = False
self._expensive_date_attr = None
def _expensive_init():
time.sleep(10)
self._expensive_date_attr = date.today()
self._assembled = True
@memoize
def date_str():
if self._assembled is False:
self._expensive_init()
return str(self._expensive_date_attr)
@memoize
def month_num():
if self._assembled is False:
self._expensive_init()
return self._expensive_date_attr.month
But that's not very clean. Ideally I'd like this behavior to either be at a class-level—but I've struggled in my attempts to overwrite __getattr__ or __getattribute__. Another decorator would also work.
I'm sorry if the above was confusing. Let me know if I can clarify it in any way!
EDIT 1: I think the above example is a little too simple. Let's say my _expensive_init() does a bunch of stuff, as opposed to just defining a single attribute.
def _expensive_init(self):
time.sleep(5)
self._expensive_date_attr = date.today()
time.sleep(1)
# send a message to someone saying that this occurred
time.sleep(1)
# run a db call to update when this action occurred
etc...
Ideally this method would handle a variety of different behaviors.
__getattr__which catches the first access to names in the table, calls the function and adds the result as a regular attribute. Hope it helps.