在 Python 中使用带有重写构造函数的抽象 class
Using abstract class with overridden constructor in Python
我正尝试在 Python 中使用带有 abc 的模板方法模式来创建可扩展的基础 class。首先,我需要派生的 classes 之一的构造函数来实现从基础构造函数调用的挂钩方法。本质上,MyBase 的所有基 classes 都将具有 attr1 和 attr2,但只有 ChildOne 需要验证属性。因此,我不想将初始化移动到 child classes,因为那将是明显的重复(这里的逻辑是微不足道的,但在现实世界的应用程序中,显然它会变得更加复杂).这就是我在基地 class:
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
我的第一个 child class 代码如下所示:
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。我尝试使用 class 方法,但我得到了相同的结果。从逻辑上讲,我似乎在尝试从 parent class 调用 child class 的逻辑,这显然违背了任何人在 OO [=32] 中学到的一切=].我如何使用模板方法模式在 parent class 中使用钩子方法来实现此功能,以便 super() 运行 child class 中的已实现版本?
Using MyBase.validate_attrs
明确表示要使用 MyBase
的版本。但是您不必这样做; self
将成为实际 child class 的实例,因此您可以将其更改为:
self.validate_attrs(attr1, attr2)
它将调用找到的第一个实现,从实际初始化的 child class 处开始搜索。无需使其成为 classmethod
,Python 中的 staticmethod
可以直接在实例上调用(装饰器确保它们不会传递 self
或 cls
即使在实例上调用时也是隐式的)。
我正尝试在 Python 中使用带有 abc 的模板方法模式来创建可扩展的基础 class。首先,我需要派生的 classes 之一的构造函数来实现从基础构造函数调用的挂钩方法。本质上,MyBase 的所有基 classes 都将具有 attr1 和 attr2,但只有 ChildOne 需要验证属性。因此,我不想将初始化移动到 child classes,因为那将是明显的重复(这里的逻辑是微不足道的,但在现实世界的应用程序中,显然它会变得更加复杂).这就是我在基地 class:
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
我的第一个 child class 代码如下所示:
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。我尝试使用 class 方法,但我得到了相同的结果。从逻辑上讲,我似乎在尝试从 parent class 调用 child class 的逻辑,这显然违背了任何人在 OO [=32] 中学到的一切=].我如何使用模板方法模式在 parent class 中使用钩子方法来实现此功能,以便 super() 运行 child class 中的已实现版本?
Using MyBase.validate_attrs
明确表示要使用 MyBase
的版本。但是您不必这样做; self
将成为实际 child class 的实例,因此您可以将其更改为:
self.validate_attrs(attr1, attr2)
它将调用找到的第一个实现,从实际初始化的 child class 处开始搜索。无需使其成为 classmethod
,Python 中的 staticmethod
可以直接在实例上调用(装饰器确保它们不会传递 self
或 cls
即使在实例上调用时也是隐式的)。