简体   繁体   English

Python:如何使用所有大写命名约定和 linter 警告创建抽象类属性

[英]Python: how to make abstract class attribute, with all caps naming convention and linter warnings

I have an abstract base class, with a constant class attribute.我有一个抽象基类,具有一个常量类属性。

How can I force a child class to override it?如何强制子类覆盖它?

I would like to keep the all caps PEP8 convention for constants.我想保留常量的全部大写 PEP8 约定


Sample Code示例代码

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"


Potential Solutions潜在的解决方案

There is a very similar question already on here: Abstract attributes in Python这里已经有一个非常相似的问题: Python 中的抽象属性

However, all the answers seem to be workarounds.但是,所有答案似乎都是解决方法。 I am wondering, is there a simpler way?我想知道,有没有更简单的方法?

Answer: https://stackoverflow.com/a/58321197/11163122答案: https : //stackoverflow.com/a/58321197/11163122

Instructs to use two decorators: abstractmethod + property指示使用两个装饰器: abstractmethod + property

  • Pros: Linter informs me if child class doesn't implement CONST_CLASS_ATTR , and cannot instantiate at runtime due to it being abstract优点:Linter 会通知我子类是否没有实现CONST_CLASS_ATTR ,并且由于它是抽象的而无法在运行时实例化
  • Cons: Linter ( pylint ) now complains invalid-name , and I would like to keep the constants have all caps naming convention缺点: 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"

Answer: https://stackoverflow.com/a/55544173/11163122答案: https : //stackoverflow.com/a/55544173/11163122

Instructs to use the dunder method __init_subclass__ .指示使用 dunder 方法__init_subclass__ This is better, as my linter no longer complains, but it's less obvious.这更好,因为我的 linter 不再抱怨,但它不那么明显。

  • Pros: Linter no longer complains about invalid-name , and cannot instantiate at runtime due to raising a NotImplementedError优点:Linter 不再抱怨invalid-name ,并且由于引发NotImplementedError无法在运行时实例化
  • Cons: Linter no longer warns if child class doesn't implement CONST_CLASS_ATTR .缺点:如果子类没有实现CONST_CLASS_ATTR不再发出警告。 Also, this seems verbose to me另外,这对我来说似乎很冗长
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"

I am using Python 3.6我正在使用 Python 3.6

I think the property decorator approach is the cleanest.我认为属性装饰器方法是最干净的。 Just silence pylint:只是沉默pylint:

@abstractmethod
@property
def CONST_CLASS_ATTR(self) -> str:  # pylint: disable=invalid-name
    return "base"

This will only silence the warning for this specific method and its overrides.这只会使针对此特定方法及其覆盖的警告静音。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM