为了账号安全,请及时绑定邮箱和手机立即绑定

一种模式,其中一个类具有许多相似的方法(相同的类型签名,相似的语义)

一种模式,其中一个类具有许多相似的方法(相同的类型签名,相似的语义)

拉风的咖菲猫 2021-03-12 15:10:52
很难抽象地描述这一点,所以让我举一个(简化和摘录的)示例:class ClassificationResults(object):  #####################################################################################################################  # These methods all represent aggregate metrics. They all follow the same interface: they return a tuple  # consisting of the numerator and denominator of a fraction, and a format string that describes the result in terms  # of that numerator, denominator, and the fraction itself.  #####################################################################################################################  metrics  = ['recall', 'precision', 'fmeasure', 'f2measure', 'accuracy']  # ...  def recall(self):    tpos, pos = 0, 0    for prediction in self.predictions:      if prediction.predicted_label == 1:        pos += 1        if prediction.true_label == 1:          tpos += 1    return tpos, pos, "{1} instances labelled positive. {0} of them correct (recall={2:.2})"  def precision(self):    tpos, true = 0, 0    for prediction in self.predictions:      if prediction.true_label == 1:        true += 1        if prediction.predicted_label == 1:          tpos += 1    return tpos, true, "{1} positive instances. We labelled {0} correctly (precision={2:.2})"  # ...  def printResults(self):    for methodname in self.metrics:      (num, denom, msg) = getattr(self, methodname)()      dec = num/float(denom)      print msg.format(num, denom, dec)有没有更好的方法来表明这些方法都属于同一个“族”,并允许它们在循环中被调用而无需每次都对其进行命名?我过去做过的另一种方法是用通用前缀命名方法,例如  def metric_precision(self):    tpos, true = 0, 0    for prediction in self.predictions:      if prediction.true_label == 1:        true += 1        if prediction.predicted_label == 1:          tpos += 1    return tpos, true, "{1} positive instances. We labelled {0} correctly (precision={2:.2})"我还可以将每个方法都转换为一个公共超类的实例,但是这感觉有点过头了。
查看完整描述

3 回答

?
慕勒3428872

TA贡献1848条经验 获得超6个赞

  • 您可以使用类装饰器来生成度量标准方法的列表。这样做的好处是,您可以在类定义时生成度量标准方法的列表,而不是每次 printResults调用都重新生成该列表。

    另一个优点是您不必手动维护ClassificationResults.metrics列表。您无需在两个位置上拼写方法的名称,因此它是DRY-er,而且,如果您添加了另一个指标,则不必记住也要更新ClassificationResults.metrics。您只需要给它一个以开头的名称即可metrics_

  • 由于每种度量方法都返回一个相似的对象,因此您可以考虑将该概念形式化为类(例如Metric,下面的)。这样做的一个好处是您可以定义一种__repr__方法来处理结果的打印方式。注意printResults (下面)变得多么简单。

def register_metrics(cls):

    for methodname in dir(cls):

        if methodname.startswith('metric_'):

            method = getattr(cls, methodname)

            cls.metrics.append(method)

    return cls



class Metric(object):

    def __init__(self, pos, total):

        self.pos = pos

        self.total = total


    def __repr__(self):

        msg = "{p} instances labelled positive. {t} of them correct (recall={d:.2g})"

        dec = self.pos / float(self.total)

        return msg.format(p=self.total, t=self.pos, d=dec)



@register_metrics

class ClassificationResults(object):

    metrics = []


    def metric_recall(self):

        tpos, pos = 1, 2

        return Metric(tpos, pos)


    def metric_precision(self):

        tpos, true = 3, 4

        return Metric(tpos, true)


    def printResults(self):

        for method in self.metrics:

            print(method(self))


foo = ClassificationResults()

foo.printResults()


查看完整回答
反对 回复 2021-03-29
  • 3 回答
  • 0 关注
  • 148 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信