我有一个抽象基类,具有常量class属性。
如何强制子类覆盖它?
我想保留常数的所有caps PEP8约定。
样本代码
from abc import ABC
class BaseClass(ABC):
"""Some abstract base class."""
# How do I force children to override this?
CONST_CLASS_ATTR = "base"
class ChildClass(BaseClass):
"""Child class."""
CONST_CLASS_ATTR = "child"
潜在解决方案
这里已经有一个非常相似的问题:Python 中的抽象属性
然而,所有的答案似乎都是变通办法。我想知道,有没有更简单的方法?
答案:https://stackoverflow.com/a/58321197/11163122
指示使用两个装饰器:abstractmethod
+property
- 优点:如果子类没有实现
CONST_CLASS_ATTR
,并且由于抽象而无法在运行时实例化,Linter会通知我 - 缺点:Linter(
pylint
(现在抱怨invalid-name
,我想保留常量的全大写命名约定
from abc import ABC, abstractmethod
class AnotherBaseClass(ABC):
"""Some abstract base class."""
@abstractmethod
@property
def CONST_CLASS_ATTR(self) -> str:
return "base"
class AnotherChildClass(AnotherBaseClass):
"""Child class."""
@property
def CONST_CLASS_ATTR(self) -> str:
return "child"
答案:https://stackoverflow.com/a/55544173/11163122
指示使用dunder方法__init_subclass__
。这更好了,因为我的门楣不再抱怨,但不那么明显了。
- 优点:Linter不再抱怨
invalid-name
,并且由于引发NotImplementedError
而无法在运行时实例化 - 缺点:如果子类没有实现
CONST_CLASS_ATTR
,Linter将不再发出警告。此外,这对我来说似乎很冗长
from abc import ABC
class YetAnotherBaseClass(ABC):
"""Some abstract base class."""
CONST_CLASS_ATTR: str
@classmethod
def __init_subclass__(cls):
if not hasattr(cls, 'CONST_CLASS_ATTR'):
raise NotImplementedError(
f"Class {cls} lacks required CONST_CLASS_ATTR class attribute.")
class YetAnotherChildClass(YetAnotherBaseClass):
"""Child class."""
CONST_CLASS_ATTR = "child"
我正在使用Python 3.6
我认为属性装饰器方法是最干净的。只是沉默:
@abstractmethod
@property
def CONST_CLASS_ATTR(self) -> str: # pylint: disable=invalid-name
return "base"
这只会使此特定方法及其覆盖的警告静音。