我试图在类中的某些方法上实现一个装饰器,因此如果该值尚未被计算,则该方法将计算该值,否则它将返回预先计算的值,该值存储在实例defaultdict
中。我似乎不知道如何从类之外声明的装饰器内部访问实例cc。对如何实施这个有什么想法吗?
以下是导入(对于一个工作示例):
from collections import defaultdict
from math import sqrt
这是我的装饰师:
class CalcOrPass:
def __init__(self, func):
self.f = func
#if the value is already in the instance dict from SimpleData,
#don't recalculate the values, instead return the value from the dict
def __call__(self, *args, **kwargs):
# can't figure out how to access/pass dict_from_SimpleData to here :(
res = dict_from_SimpleData[self.f.__name__]
if not res:
res = self.f(*args, **kwargs)
dict_from_SimpleData[self.f__name__] = res
return res
下面是带修饰方法的SimpleData类:
class SimpleData:
def __init__(self, data):
self.data = data
self.stats = defaultdict() #here's the dict I'm trying to access
@CalcOrPass
def mean(self):
return sum(self.data)/float(len(self.data))
@CalcOrPass
def se(self):
return [i - self.mean() for i in self.data]
@CalcOrPass
def variance(self):
return sum(i**2 for i in self.se()) / float(len(self.data) - 1)
@CalcOrPass
def stdev(self):
return sqrt(self.variance())
到目前为止,我试着在simpledata中声明装饰者,试着和装饰者进行多次争论(显然你不能这么做),在我的转椅上转来转去,同时试着把纸飞机扔进我的蝎子坦克。任何帮助都将不胜感激!
最佳答案
定义装饰器的方式目标对象信息丢失。改用函数包装器:
def CalcOrPass(func):
@wraps(func)
def result(self, *args, **kwargs):
res = self.stats[func.__name__]
if not res:
res = func(self, *args, **kwargs)
self.stats[func.__name__] = res
return res
return result
wraps
是从functools
开始的,在这里并不严格必要,但非常方便。旁注:
defaultdict
采用工厂函数参数:defaultdict(lambda: None)
但是,既然你正在测试密钥的存在,你应该选择一个简单的
dict
。