У меня есть абстрактный базовый класс с атрибутом константного класса.
Как я могу заставить дочерний класс переопределить его?
Я хотел бы оставить все заглавные буквы Соглашение 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
Однако все ответы кажутся обходными. Мне интересно, есть ли более простой способ?
Ответ: { ссылка }
Указывает использовать два декоратора: abstractmethod
+ property
- Плюсы: Линтер сообщает мне, если дочерний класс не реализует
CONST_CLASS_ATTR
и не может создать экземпляр во время выполнения из-за его абстрактности - Минусы: Линтер (
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"
Ответ: { ссылка }
Указывает использовать метод dunder __init_subclass__
. Это лучше, так как мой линтер больше не жалуется, но он менее очевиден.
- Плюсы: Линтер больше не жалуется на
invalid-name
и не может быть создан во время выполнения из-за повышения NotImplementedError
- Минусы: Линтер больше не предупреждает, если дочерний класс не реализует
CONST_CLASS_ATTR
. Кроме того, это кажется мне многословным
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