【问题标题】:Using abstract class with overridden constructor in Python在 Python 中使用带有重写构造函数的抽象类
【发布时间】:2020-04-12 14:38:02
【问题描述】:

我正在尝试在 Python 中使用带有 abc 的模板方法模式来创建可扩展的基类。首先,我需要派生类之一的构造函数来实现从基类的构造函数调用的钩子方法。本质上,MyBase 的所有基类都有 attr1 和 attr2,但只有 ChildOne 需要验证属性。因此,我不想将初始化移动到子类,因为这将是明显的重复(这里的逻辑很简单,但在现实世界的应用程序中,显然它会变得更加复杂)。这就是我在基类中的内容:

import abc

class MyBase(abc.ABC):
    @abc.abstractmethod
    def __init__(self, attr1, attr2):
        # this is only implemented in one child class
        MyBase.validate_attrs(attr1, attr2)
        self.attr1 = attr1
        self.attr2 = attr2

    @staticmethod
    @abc.abstractmethod
    def validate_attrs(attr1, attr2):
        """ In Child1, raise exception if attr1 or attr2 are invalid """
        pass

我的第一个子类的代码如下所示:

class ChildOne(MyBase):
    def __init__(self, attr1, attr2, attr3):
        # this class will implement validate_attrs, and logic needs to be called here
        super().__init__(attr1, attr2)
        self.attr3 = attr3

    # Override default from MyBase
    @staticmethod
    def validate_attrs(attr1, attr2):
        if attr1 < attr2:
            raise ValueError("attr1 is too small!")  # this is just stand in logic to keep it brief

但是,当我使用此代码实例化 ChildOne 时

c1 = ChildOne(1, 2, 3)

使用默认的pass。我知道这一点是因为没有引发 ValueError,即使 1(attr1) 小于 2(attr2)。我想这是意料之中的,因为我专门调用了 MyBase.validate_attrs。我尝试使用类方法,但得到相同的结果。从逻辑上讲,我似乎试图从父类调用子类的逻辑,这显然与任何人在 OO 类中学到的一切背道而驰。如何使用模板方法模式在父类中使用钩子方法实现此功能,以便 super() 在子类中运行实现的版本?

【问题讨论】:

  • 我不太明白为什么这篇文章被否决了,因为我已经与版主讨论了如何使其更清晰,并相应地编辑了这篇文章。也许投反对票的人可以留下有用的评论,以帮助我避免将来犯的任何错误

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


【解决方案1】:

使用MyBase.validate_attrs 明确表示使用MyBase 的版本。但你不必; self 将成为实际子类的一个实例,因此您可以将其更改为:

self.validate_attrs(attr1, attr2)

它会调用找到的第一个实现,从实际初始化的子类开始搜索。无需将其设为classmethod,Python 中的staticmethods 可以直接在实例上调用(装饰器确保即使在实例上调用它们也不会隐式传递selfcls)。

【讨论】:

  • 似乎我为将火箭筒带入刀战这个古老的问题而祈祷。一旦我做出改变,我所有的单元测试都通过了。我反对使用self,因为ChildOne 中的方法体从不引用它,而且我总是被教导这样的方法应该在函数之外创建。但我想这是一个特例,如果它有效,它就有效。感谢您的帮助。
猜你喜欢
  • 1970-01-01
  • 2011-03-21
  • 1970-01-01
  • 2011-03-16
  • 2023-03-13
  • 2012-07-22
  • 2018-10-12
  • 2011-11-17
相关资源
最近更新 更多