Accessing self from outside of a class
decorator, python
Solution
The way you define your decorator the target object information is lost. Use a function wrapper instead:
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` is from `functools` and not strictly necessary here, but very convenient.
Side note: `defaultdict` takes a factory function argument:
defaultdict(lambda: None)
But since you're testing for the existence of the key anyway, you should prefer a simple `dict`.
Problem
I'm attempting to implement a decorator on certain methods in a class so that if the value has NOT been calculated yet, the method will calculate the value, otherwise it will just return the precomputed value, which is stored in an instance `defaultdict`. I can't seem to figure out how to access the instance `defaultdict` from inside of a decorator declared outside of the class. Any ideas on how to implement this? Here are the imports (for a working example): ``` from collections import defaultdict from math import sqrt ``` Here is my decorator: ``` 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 ``` And here's the SimpleData class with decorated methods: ``` 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()) ``` So far, I've tried declaring the decorator inside of SimpleData, trying to pass multiple arguments with the decorator(apparently you can't do this), and spinning around in my swivel chair while trying to toss paper airplanes into my scorpion tank. Any help would be appreciated!