第一类属性访问上的Python自定义初始化
我们的目标是创建一个自定义python类,该类允许懒散地加载属性(这是一个相当常见的问题,这里有各种不同的解决方案),但在惰性访问中只运行一次昂贵的初始化步骤。下面是一个例子:第一类属性访问上的Python自定义初始化,python,python-2.7,lazy-loading,lazy-evaluation,Python,Python 2.7,Lazy Loading,Lazy Evaluation,我们的目标是创建一个自定义python类,该类允许懒散地加载属性(这是一个相当常见的问题,这里有各种不同的解决方案),但在惰性访问中只运行一次昂贵的初始化步骤。下面是一个例子: class LazyDateModule() def __init__(self, args): self.args = args self._expensive_date_attr = None def _expensive_init(): time.s
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()
如何仅在第一次访问任何已记忆的属性方法时运行\u 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
但那不是很干净。理想情况下,我希望这种行为要么是在类级别上,要么是在试图覆盖\uuuu getattr\uuu
或\uu getattribute\uuu
时遇到了困难。另一个装饰师也会工作
很抱歉,如果上面的内容让人困惑的话。如果我能以任何方式澄清,请告诉我
编辑1:
我觉得上面的例子有点太简单了。假设我的_昂贵的_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...
理想情况下,此方法可以处理各种不同的行为。您有一个缓存装饰器
memoize
,那么为什么不使用它来缓存您的\u昂贵的\u日期\u属性呢?顺便说一句,把它变成一个财产:
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
有没有理由把日期和月数也记下来?没有别的原因,就是它们都记在了你的代码里。这是干净的,但不幸的是,我认为这对我的设想不起作用。这方面的例子太简单了。查看我最近的更改。假设你的memoize
decorator做了一件显而易见的事情(即,在第一次调用时记住一个方法结果,并在下一次调用时直接返回),我不明白为什么你认为它对你的编辑不起作用。如果需要,您可以使用functools.lru\u cache
来实现这一效果。另外,请注意\u昂贵的\u date\u attr()
方法没有设置任何属性,而是由它自己编写的一个类似模块的属性。我决定不完成它。它分两步工作。在第一步中,简单方法装饰器通过向装饰函数本身添加属性来注册每个要记忆的方法。该类本身在当时并不存在,所以只能这样做。在第二步中,类装饰器检查添加属性的所有方法,创建一个表,从类中删除这些方法,并安装一个自定义的\uuuu getattr\uuuuu
,它捕获对表中名称的第一次访问,调用函数并将结果作为常规属性添加。希望能有帮助。