Let's say I have a class like this. from scipy import interpolate import numpy as np class Bar: def __init__(self,data): self.data = data def mean(self): return self.data.mean(axis=0) def sd(self): return self.data.std(axis=0) bar = Bar(np.random.rand(10,5)) print(bar.mean()) print(bar.sd()) The class Bar may have many such methods such as mean(), sd() etc. I want to add sampled versions of those methods, so that I can simply get results equivalent to this: new_ids = np.linspace(bar.ids[0],bar.ids[-1],100) sampled_mean = interpolate.interp1d(bar.ids,bar.mean(),axis=0)(new_ids) Current workaround: manually add new methods with help of decorators. from scipy import interpolate import numpy as np def sample(func): def wrapper(self,n_sample=100,*args,**kwargs): new_ids = np.linspace(self.ids[0],self.ids[-1],n_sample) vals = func(self,*args,**kwargs) return interpolate.interp1d(self.ids,vals,axis=0)(new_ids) return wrapper class Bar: def __init__(self,ids,data): self.ids = ids self.data = data def mean(self): return self.data.mean(axis=0) def sd(self): return self.data.std(axis=0) @sample def spl_mean(self): return self.mean() @sample def spl_sd(self): return self.sd() bar = Bar(ids=np.arange(5),data=np.random.rand(10,5)) new_ids = np.linspace(bar.ids[0],bar.ids[-1],100) sampled_mean = interpolate.interp1d(bar.ids,bar.mean(),axis=0)(new_ids) assert np.all(sampled_mean == bar.spl_mean()) However, I have many such methods. Of course I can write them with the help of LLM but what I want to know is: whether this is already a good practice to achieve this, and whether there's more elegant approache. Continue reading...