目标是创建一个自定义python类,允许延迟加载属性(这里有一个相当常见的问题,使用各种不同的解决方案),但只有在懒惰访问时才运行昂贵的初始化步骤。这是一个例子:
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
在这个例子中,我的@memoize
装饰器为我处理了缓存步骤。
如果我在其他地方定义我的LazyDateModule:
LDM = LazyDateModule()
如何在第一次访问任何memoized属性方法时运行_expensive_init()
?我尝试过这样的事情:
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
但那不是很干净。理想情况下,我希望这种行为要么处于班级水平 - 但我在尝试覆盖__getattr__
或__getattribute__
时遇到了困难。另一个装饰也行。
如果上述情况令人困惑,我很抱歉。如果我能以任何方式澄清它,请告诉我!
编辑1: 我认为上面的例子有点过于简单了。假设我的_expensive_init()做了很多事情,而不是仅定义一个属性。
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...
理想情况下,此方法可以处理各种不同的行为。
答案 0 :(得分:2)
你有一个缓存装饰器memoize
,那么为什么不用它来缓存你的_expensive_date_attr
?和BTW把它变成一个属性:
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