Seb*_*ian 5 python lazy-loading decorator
我有一个代表系统的状态对象.状态对象中的属性从[huge]文本文件中填充.因为每次创建状态实例时都不会访问每个属性,所以延迟加载它们是有意义的:
class State:
def import_positions(self):
self._positions = {}
# Code which populates self._positions
@property
def positions(self):
try:
return self._positions
except AttributeError:
self.import_positions()
return self._positions
def import_forces(self):
self._forces = {}
# Code which populates self._forces
@property
def forces(self):
try:
return self._forces
except AttributeError:
self.import_forces()
return self._forces
Run Code Online (Sandbox Code Playgroud)
这里有很多重复的样板代码.此外,有时import_abc可以填充一些变量(即,如果已经打开,则从一个小数据文件中导入一些变量).
重载@property是有意义的,它接受一个"提供"该变量的函数,即:
class State:
def import_positions(self):
self._positions = {}
# Code which populates self._positions
@lazyproperty(import_positions)
def positions(self):
pass
def import_forces(self):
self._forces = {}
# Code which populates self._forces and self._strain
@lazyproperty(import_forces)
def forces(self):
pass
@lazyproperty(import_forces)
def strain(self):
pass
Run Code Online (Sandbox Code Playgroud)
但是,我似乎无法找到一种方法来准确追踪@property装饰器中正在调用的方法.因此,我不知道如何将@property重载到我自己的@lazyproperty中.
有什么想法吗?
也许你想要这样的东西。这是一种与@property.
def lazyproperty(func):
values = {}
def wrapper(self):
if not self in values:
values[self] = func(self)
return values[self]
wrapper.__name__ = func.__name__
return property(wrapper)
class State:
@lazyproperty
def positions(self):
print 'loading positions'
return {1, 2, 3}
s = State()
print s.positions
print s.positions
Run Code Online (Sandbox Code Playgroud)
哪个打印:
loading positions
set([1, 2, 3])
set([1, 2, 3])
Run Code Online (Sandbox Code Playgroud)
警告:值字典中的条目不会被垃圾收集,因此它不适合长时间运行的程序。如果加载的值在所有类中都是不可变的,则可以将其存储在函数对象本身上,以获得更好的速度和内存使用:
try:
return func.value
except AttributeError:
func.value = func(self)
return func.value
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
473 次 |
| 最近记录: |