在Python中实现抽象类的最佳方法是什么?
这是我所看到的主要方法:
class A(ABC):
@abstractmethod
def foo(self):
pass
但是,在扩展该类时,它不会阻止调用抽象方法。
在Java中,如果尝试执行类似的操作会出错,但在Python中则不会:
class B(A):
def foo(self):
super().foo()
B().foo() # does not raise an error
为了复制相同的Java行为,您可以采用这种方法:
class A(ABC):
@abstractmethod
def foo(self):
raise NotImplementedError
但是,实际上,即使是最正确的解决方案,我也很少见到后者。是否有特定原因偏爱第一种方法而不是第二种方法?
如果您真的希望在子类之一尝试调用超类抽象方法时引发错误,那么,是的,您应该手动引发它。
现有行为实际上是很方便的:如果您的抽象方法仅包含pass
,则可以在基类中插入任意数量的子类,并且只要至少一个实现抽象方法,它就可以工作。即使它们全部调用了super()等效方法,也没有检查其他任何内容。
[如果发生错误-在复杂的层次结构中将使用mixins调用NotImplementedError
或其他方式,则需要在每次调用super
时检查是否引发了错误,只是跳过它。 (检查super()
是否会打到有条件的抽象方法可行的类,但甚至会导致模式复杂)。
由于如果您想要到达方法的层次结构的基础,就是什么都不做,那么什么也不做就很简单!
我是说,检查一下:
class A(abc.ABC):
@abstractmethod
def validate(self, *kwargs):
pass
class B(A):
def validate(self, *, first_arg_for_B, second_arg_for_B=None, **kwargs):
super().validate(**kw,args)
# perform validation:
...
class C(A)
def validate(self, *, first_arg_for_C **kwargs):
super().validate(**kwargs)
# perform validation:
...
class Final(B, C):
...
B.validate和C.validate都不需要担心层次结构中的任何其他类,只需执行他们的操作并继续下去。如果A.validate会提高,则这两种方法都必须在super().validate(...)
语句内或在怪异的try: ...;except ...:pass
块内执行if
,以获取任何好处。