如何使用setattr继承类方法/属性而不会出现属性错误:'cls'对象的'__weakref__'是不可写的

问题

我想参数化不同的数据分布。每个发行版都定义为自己的类。这样,每个分布都可以共享属性名称(例如pdf用于概率分布,否则为f)。例如,请考虑两个数据集-一个数据集遵循直线模型,而另一个数据集遵循正态分布。我想有一个“主”类(因为缺少更好的词),它可以继承所选发行版的属性。我知道可以在构造函数中使用super().__init__()从父类继承,但是我不知道如何从所有父类继承。我希望没有代表不同分布的类互相继承。因此,我认为可以为此目的使用setattr,但出现以下错误:

line 54,in initialize_model
    setattr(self,attribute,getattr(model,attribute))
AttributeError: attribute '__weakref__' of 'NormalDistribution' objects is not writable

问题

什么是弱引用,为什么它不可写?我的方法可以适应工作吗,还是有更好的方法?

我的尝试

## imports
import numpy as np
import matplotlib.pyplot as plt

## first distribution
class NormalDistribution():

    def __init__(self):
        self.nparams = 2

    @staticmethod
    def pdf(prms,x):
        return np.exp(- np.square((x - prms[0])/prms[1]) / 2) / (prms[1] * np.sqrt(2 * np.pi))

    @staticmethod
    def get_parameter_guess(x,**kwargs):
        mu,sigma = np.mean(x),np.std(x,**kwargs)
        return (mu,sigma)

## second distribution
class LinearEquation():

    def __init__(self):
        self.nparams = 2

    @staticmethod
    def f(prms,x):
        return prms[0] * x + prms[1]

    @staticmethod
    def get_parameter_guess(x,y):
        dy = y[-1] - y[0]
        dx = x[-1] - x[0]
        m = dy / dx
        b = np.mean([y[idx] - m * x[idx] for idx in (0,-1)])
        return (m,b)

## I want this to inherit methods/attributes
## specified by distribution_model
class Distributionmodel():

    def __init__(self,distribution_model):
        self._distribution_model = None
        self.initialize_model(distribution_model)

    @property
    def available_distribution_models(self):
        result = {}
        result['linear equation'] = LinearEquation()
        result['normal distribution'] = NormalDistribution()
        return result

    def initialize_model(self,distribution_model):
        if distribution_model not in list(self.available_distribution_models.keys()):
            raise ValueError("invalid distribution_model: {}".format(distribution_model))
        self._distribution_model = distribution_model
        model = self.available_distribution_models[distribution_model]
        for attribute in dir(model):
            setattr(self,attribute))

要致电

Model = Distributionmodel('normal distribution')

np.random.seed(327)
prms = (50,10)
data = np.random.normal(loc=prms[0],scale=prms[1],size=100).astype(int)
x = np.sort(data)
y = Model.f(prms,x)

fig,ax = plt.subplots()
ax.plot(x,y)
plt.show()
plt.close(fig)
zhuzheqi2096409 回答:如何使用setattr继承类方法/属性而不会出现属性错误:'cls'对象的'__weakref__'是不可写的

我找到了适合我情况的解决方法。也许这对其他人会有帮助,但是也许有更好的方法?

我在LinearEquationNormalDistribution的类定义下面添加了函数。

def get_kwargs(self):
    result = {}
    result['pdf'] = self.pdf
    result['get_parameter_guess'] = self.get_parameter_guess
    return result

然后,将类initialize_model(distribution_model)中的函数DistributionModel更改为以下内容:

def initialize_model(self,distribution_model):
    if distribution_model not in list(self.available_distribution_models.keys()):
        raise ValueError("invalid distribution_model: {}".format(distribution_model))
    self._distribution_model = distribution_model
    model = self.available_distribution_models[distribution_model]
    for key,attribute in model.get_kwargs().items():
        setattr(self,key,attribute)
本文链接:https://www.f2er.com/2818248.html

大家都在问