1

我创建了一个包含 3 个主要内容的模块:

  1. 具有方法的主类__new__和继承该方法的子类;
  2. make_method可以将方法关联到现有类的装饰器:
def make_method(obj):
    '''Decorator to make the function a method of *obj*.
    In the current context::
      @make_method(Axes)
      def toto(ax, ...):
          ...
    makes *toto* a method of `Axes`, so that one can directly use:
      ax.toto()
    COPYRIGHT: from Yannick Copin
    '''
    def decorate(f):
        setattr(obj, f.__name__, f)
        return f
    return decorate
  1. 一个generic班。

主类有一个__new__方法,该方法使用make_method装饰器创建适用于任何子类的绘图函数。这是示例:

class MainClass():

    FREEPARAMETERS = ['mu_1', 'sigma_1']
    PLTALL = ["self.param['" + k + "']" for k in FREEPARAMETERS]

    def __new__(cls, *arg, **kwargs):
        '''Returns the class with dynamically generated methods'''
        obj = super(MainClass, cls).__new__(cls)

        exec("@make_method(MainClass)\n" +
             "def plot_a(self, x_lin):\n" +
             "    return self.likelihood_tot(x_lin, %s)"
             % (", ".join(MainClass.PLTALL)))

       return(obj)

然后,如果我以ChildClass这种方式创建:

class ChildClass(MainClass):

    FREEPARAMETERS = ['mu_1', 'sigma_1', 'mu_2', 'sigma_2']
    PLTALL = ["self.param['" + k + "']" for k in FREEPARAMETERS]

它将有一个plot_a方法,只需要一个,x_lin而不必手动输入参数(提供一个likelihood_tot采用正确参数的方法)。

所有这些都非常有效(对于我真正需要的东西来说,这可能有点矫枉过正,但它很甜蜜)。然后generic上课:

class generic():
    '''Usage:
       gen = MyModule.generic()
       gen.set_model('model')
       fitted_model_1 = gen.fit(dataset1)
       fitted_model_2 = gen.fit(dataset2)

       fitted_model_1.plot_a(x_lin)
       fitted_model_2.plot_a(x_lin)'''

    def set_model(self, classname):
        '''Associates an uninstantiated class to self.model from its string'''
        self.model = getattr(sys.modules[__name__], classname)

    def fit(self, dataset, **kwargs):
        '''Instantiates the class with the pandas,
        apply the `minimize` method,
        and gives that back as an output'''

        model = self.model(dataset)
        model.minimize(**kwargs)
        return(model)

正如其文档中所述,这个想法是能够调用一个通用模型,例如,我可以将不同的数据集传递给该模型,而不必每次都手动实例化该类。工作正常。

执行以下操作时会出现问题,在哪里ChildClass1ChildClass2有不同FREEPARAMETERS

gen.set_model('ChildClass1')
fitted_childclass1 = gen.fit(dataset)

gen.set_model('ChildClass2')
fitted_childclass2 = gen.fit(dataset)

fitted_childclass2.plot_a(x_lin)
fitted_childclass1.plot_a(x_lin)

第一个plot_a(x_lin)generic类的最后一次调用相关联,工作正常。然而,第二个根据最新实例类和之前实例类之间的相对数量给我一个KeyError: 'mu_2'或一个,这意味着不知何故,动态生成now 具有 的参数TypeError: likelihood_tot() missing n required positional argumentsFREEPARAMETERSplot_afitted_childclass1fitted_childclass2

然而,当调用childclass1.PLTALLor时childclass2.PLTALL,我确实得到了预期的结果。似乎它们在实例化后没有互换。所有不是动态生成的方法都是正确的。

我当然可以调用plot_a每个函数之间的函数,但这显然不是重点。我想要两者childclass1并且childclass2表现得好像我实例化它们一样:

childclass1 = MyModule.ChildClass1(dataset)
childclass1.minimize()
childclass2 = MyModule.ChildClass2(dataset)
childclass2.minimize()
4

0 回答 0