python - 类模板的习惯用法或设计模式?

标签 python class design-patterns

我的代码库是Python 的。假设我有一个相当通用的类,称为 Report。它需要大量参数

class Report(object):
  def __init__(self, title, data_source, columns, format, ...many more...)

并且该报告有很多很多实例。这些实例化并非完全无关。许多报告共享相似的参数集,仅存在细微的变化,例如具有相同的 data_source 和列,但标题不同。

应用一些编程构造来使表达该结构更容易,而不是重复参数。我正在尝试寻找一些帮助来理清思路,以确定一些惯用语或设计模式。

如果报表的子类别需要一些额外的处理代码,子类似乎是一个不错的选择。假设我们有一个 ExpenseReport 的子类别。

class ExpenseReport(Report):
    def __init__(self, title, ... a small number of parameters ...)

        # some parameters are fixed, while others are specific to this instance
        super(ExpenseReport,self).__init__(
                title,
                EXPENSE_DATA_SOURCE,
                EXPENSE_COLUMNS,
                EXPENSE_FORMAT,
                ... a small number of parameters...)

    def processing(self):
        ... extra processing specific to ExpenseReport ...

但很多情况下,子类别只是修复了一些参数,没有做任何额外的处理。使用部分功能可以轻松完成。

ExpenseReport = functools.partial(Report,
                        data_source = EXPENSE_DATA_SOURCE,
                        columns = EXPENSE_COLUMNS,
                        format = EXPENSE_FORMAT,
                )

在某些情况下,甚至没有任何区别。我们只需要同一对象的 2 个副本即可在不同的环境中使用,例如嵌入到不同的页面中。

expense_report = Report("Total Expense", EXPENSE_DATA_SOURCE, ...)
page1.add(expense_report)

...
page2.add(clone(expense_report))

在我的代码库中,使用了一种丑陋的技术。因为我们每个页面需要 2 个单独的实例,并且因为我们不想重复创建报告的具有长参数列表的代码,所以我们只需克隆(在 Python 中进行深度复制)第 2 页的报告。克隆并不明显,忽略克隆对象并共享一个实例会在我们的系统中创建许多隐藏的问题和微妙的错误。

对于这种情况有什么指导吗?子类、部分函数还是其他习惯用法?我的愿望是这个结构是轻且透明的。我对子类化有点警惕,因为它可能会导致子类丛林。它会促使程序员添加特殊的处理代码,就像我在 ExpenseReport 中的代码一样。如果有需要,我宁愿分析代码,看看它是否可以通用并推送到报表层。使Report变得更有表现力,而不需要底层进行特殊处理。

其他信息

我们确实使用关键字参数。问题更多在于如何管理和组织实例化。我们有大量具有常见模式的实例化:

expense_report = Report("Expense", data_source=EXPENSE, ..other common pattern..)
expense_report_usd = Report("USD Expense", data_source=EXPENSE, format=USD, ..other common pattern..)
expense_report_euro = Report("Euro Expense", data_source=EXPENSE, format=EURO, ..other common pattern..)
...
lot more reports 
...
page1.add(expense_report_usd)
page2.add(expense_report_usd)   # oops, page1 and page2 shared the same instance?!
...
lots of pages
...

最佳答案

为什么不直接使用关键字参数并将它们全部收集到 dict 中:

class Report(object):
  def __init__(self, **params):
      self.params = params
      ...

关于python - 类模板的习惯用法或设计模式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8884140/

相关文章:

python - 如何编写 python 函数来接受 *arguments 和关键字参数?

python - 根据变量名运行不同的类?

c++ - 这个例子中的qGetPtrHelper有什么用?

java - Android Clean 架构中的登录流程

python - 在pyspark中按行连接字符串

python - 具有多种语言的 spaCy 流程文档

python - 直接引用时,是否可以在 Python 中创建表示另一种类型的类?

Jquery:如果类存在

c# - 基于接口(interface)的设计和可选方法参数

python - 运行黑色会导致错误 "This float doesn' t 有一个前导数字”