目标是创建一个自定义python类,它允许对属性进行延迟加载(这里有一个相当常见的问题,这里有各种不同的解决方案),但是一次只运行昂贵的初始化步骤懒惰的访问。这里有一个例子:对第一类属性访问的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...
理想情况下,此方法将处理各种不同的行为。
我写了一个类似的模块。我决定不完成它。它分两步工作。在第一步中,一个简单的方法装饰器通过向装饰函数本身添加一个属性来注册每个要记忆的方法。这个阶级本身并不存在,所以这就是它所能做到的。在第二步中,类装饰器检查所添加属性的所有方法,创建表,从类中移除这些方法,并安装一个自定义的__getattr__来捕获对表中名称的第一次访问,调用该函数并添加结果作为常规属性。希望能帮助到你。 – VPfB