【问题标题】:Python: Design classes with same methods and different but equivalentPython:设计具有相同方法和不同但等效的类
【发布时间】:2016-06-16 10:27:28
【问题描述】:

我有一个算法可以在不同的数据集上执行相同的任务。本质上方法相同,但参数不同。我正在尝试为此创建类,但由于我不熟悉 OOP 设计原则,所以我有点困惑如何做到这一点。

由于算法是相同的,我想我可以创建一个公共类,与两个不同数据集相关的类从该类继承。例如,

class MyAlgorithm():
    def __init__(self, column1, column2):
        self.column1 = column1
        self.column2 = column2

    def step1():
        # do sth with dataset

    def step2():
        # do sth with result of step1()

class Dataset1Class(MyAlgorithm):
    def __init__(self, dbconn, tablename='dataset2table'):
        self.dbconn = dbconn
        self.tablename = tablename

    def get_data(dbconn, tablename):
        # get data from database for one date
        (column1A, column1B) = data_query # not shown
        return column1A, column1B


class Dataset2Class(MyAlgorithm):
    def __init__(self, dbconn, tablename='dataset1table'):
        self.dbconn = dbconn
        self.tablename = tablename

    def get_data(dbconn, tablename):
        # get data from database for one date
        (column2X, column2Y) = data_query # not shown
        return column2X, column2Y 

我在这里稍微简化了一下,数据源实际上是一个数据库,但我认为这可能不是最好的方法。所以,我想知道一个有经验的 Pythonista 会如何做到这一点。还有另一种更好的方法吗?此代码是更大代码库的一部分,最终将与数据管道的其余部分一起从 Celery 工作进程中调用。

【问题讨论】:

  • 当然,我不会费心在与超类相同的子类中编写方法,但鉴于您在任何类之间没有表现出任何行为差异,因此不可能说这是否是一个好主意与否。你能举一个不那么抽象的例子吗?
  • @jonrsharpe 这本质上是一种方法相同但参数不同的情况。我确实考虑过将不同的参数发送到同一个类,但是做很多 if...elif...else 的前景对我也没有吸引力。我试图在这里遵循模板方法模式。
  • @sfactor:那么您需要确定数据之间的差异以及数据在您的问题中的处理方式。如果您有具有相同方法但参数不同的子类,那么由于函数签名不同,您可能需要以不同方式处理它们。如果数据足够相似,您可能可以使用具有兼容默认值的关键字参数。但这真的取决于数据。
  • @mhawke 我想抽象出算法并能够重用它,如果稍后说我也有不同的数据集。是否可以在不重新实现的情况下使用子类中的基类方法并根据结果进行自己的处理?我猜我需要使用 super() 方法。
  • @sfactor 是的,这是可能的,super 正是你会怎么做的。如果是类之间的处理不同,显示出来!

标签: python class python-3.x oop design-patterns


【解决方案1】:

为什么不将不同的数据集传递给您的算法类,而不是为不同的算法创建两个类。

class Algorithm:
  def __init__(self, dataset):
    self.dataset = dataset

  def method_1():
      """this is your algo implementation"""
      # perform action here on your dataset using self.dataset

【讨论】:

  • 哦,我现在正在写ruby代码,当我看到这个问题时,现在很尴尬。感谢@jonrsharpe 的更改
【解决方案2】:

如图所示,该示例根本不需要继承。

假设数据集提供相同的接口,例如元组列表或字典列表,MyAlgorithm 类足以处理这两个数据集。

如果数据格式不同,例如不同数量的字段,或者由于数据类型或语义不同而对字段有不同的处理要求,那么子类化和覆盖相关的处理方法似乎是一个合理的方法。

存在许多这种策略的例子。 Python 3 标准库中的一个是html.parser,它提供了基类HTMLParser,您可以从该基类继承并覆盖您有兴趣处理的方法,例如在看到新标签或读取一些数据时.

【讨论】:

  • 感谢您的回答和对 html.parser 实现的参考。是的,我也为您的推理而苦苦挣扎,但是这两个数据集具有不同的参数(尽管是数字的),如果我只有一个类,我将不得不做很多 if...elif...else 取决于提供的数据集。结果也将存储在不同的数据库中。这就是我尝试使用此模板模式的原因。
  • @sfactor:好的。请参阅我对您的主要问题的评论。
  • @sfactor:至于将结果存储在不同的数据库中,您可以通过将数据库连接或连接参数传递给类的__init__() 方法来处理。但这完全取决于模式是否可行。如果您在设计方面需要具体帮助,我建议您在问题中发布具体细节,否则没有足够的信息可以提供适当的建议。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多