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.
You have a caching decorator memoize, so why not use it to cache your _expensive_date_attr ? and BTW turn it into a property:
class LazyDateModule():
def __init__(self, args):
self.args = args
self._assembled = False
@memoize
@property
def _expensive_date_attr(self):
return date.today
@memoize
def date_str():
return str(self._expensive_date_attr)
@memoize
def month_num():
return self._expensive_date_attr.month
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