class 中的断言和文档,用于派生 classes 中预期的方法

Assertion & documentation in a class for methods that are expected in derived classes

假设我制作了一个名为 Bird 的 class,我只想将其用作父 class 并且派生的 classes 应该有一个方法 flap_wings :

class Bird:

    def fly(self):
        self.flap_wings()

预期派生的 class 可能如下所示:

class Eagle(Bird):

    def flap_wings(self):
        print('flapping wings')

什么是 Bird 既断言其派生的 class 具有方法 flap_wings 又包含有关 flap_wings 的文档的好方法?预计做什么?

现在,我正在使用 __init_subclass__:

class Bird:

    def fly(self):
        self.flap_wings()

    def __init_subclass__(cls, **kwargs):
        assert hasattr(cls, 'flap_wings'), (
            "Derived classes have to have a flap_wings method which should "
            "print 'flapping wings'."
        )

但是,assert 表达式仅在您创建 Bird class 后显示,而不是可以通过 help.

访问的 "real" 文档字符串

我知道这是一个开放式问题,但还有哪些更好的方法?首先在 Bird 中定义 flap_wings 并不违反规则,也许只是使用正文 pass 和文档字符串。但我就是找不到 "standard" 方法来处理这种情况。所以我正在寻找任何建议。

您可以将 abc 库用于抽象方法:

from abc import ABCMeta, abstractmethod
import six

class Bird(six.with_metaclass(ABCMeta)):
    def fly(self):
        """Take flight.

        Notes
        -----
        This depends on the abstract method `flap_wings`. If you've
        not implemented this at the subclass level, your subclass
        cannot be properly instantiated.
        """
        self.flap_wings()

    @abstractmethod
    def flap_wings(self):
        """Subclasses must implement this"""

这建立了某种契约。任何未实现 flap_wings 方法的 subclass 都会在实例化时引发错误:

class Flamingo(Bird):
    pass

>>> Flamingo()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class Flamingo with abstract methods flap_wings

而实现抽象方法的子 class 可以正常工作:

class BlueJay(Bird):
    def flap_wings(self):
        print("Flappity flap")

>>> BlueJay().fly()
Flappity flap

至于记录 subclass,因为所有 subclasses 都继承了 fly 方法,你可以在它的文档字符串中包含它调用 flap_wings方法并期望它存在。