我想创建一个属性装饰器,它在对象初始化时计算属性值,而不是每次访问属性时。例如:
$.each(data.categories, function(index, value) {
console.log(index); // current category
$.each(value, function(indexSub, valueSub) {
console.log(indexSub);
console.log(valueSub.id);
console.log(valueSub.code);
console.log(valueSub.name);
});
});
我希望这相当于:
class Foo:
def __init__(self, value):
self.value = value
@cached_property # How to implement this decorator?
def foo(self):
return self.value * some_heavy_computation()
是否有可能以某种方式从方法装饰器中向class Foo:
def __init__(self, value):
self.value = value
self._foo = self.value * some_heavy_computation()
@property
def foo(self):
return self._foo
添加代码?
答案 0 :(得分:0)
我们需要子类property
,以便稍后我们可以找到对象的所有缓存属性并在__init__
之后初始化它们:
class CachedProperty(property):
pass
实际装饰器在第一次调用时会计算方法体,并记住结果以供以后访问:
import functools
def cached_property(method):
attribute = '_cached_' + method.__name__
@CachedProperty
@functools.wraps(method)
def wrapper(self, *args, **kwargs):
if not hasattr(self, attribute):
setattr(self, attribute, method(self))
return getattr(self, attribute)
return wrapper
现在我们可以使用基类来访问__init__
之后的缓存属性,以便可以从缓存中获取这些值:
class InitCachedProperties:
def __init_subclass__(cls, **kwargs):
super().__init_subclass__(**kwargs)
orig_init = cls.__init__
def init(self, *args, **kwargs):
orig_init(self, *args, **kwargs)
for prop in cls.__dict__.values():
if isinstance(prop, CachedProperty):
prop.__get__(self)
cls.__init__ = init
为了使问题起作用,我们需要让我们的类继承这个属性初始化基类:
class Foo(InitCachedProperties):
def __init__(self, value):
self.value = value
@cached_property
def foo(self):
return self.value + 21