关于Python:assertion &在一级的文档的方法,是在衍生类增加

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

本问题已经有最佳答案,请猛点这里访问。

假设我生成一个名为bird的类,我只想将它用作父类,派生类应该有一个方法flap_wings

1
2
3
4
class Bird:

    def fly(self):
        self.flap_wings()

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

1
2
3
4
class Eagle(Bird):

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

对于Bird来说,一个好的、明确的方法是什么,它既断言其派生类具有flap_wings方法,又包含了关于flap_wings预期要做什么的文档?

现在,我正在使用__init_subclass__

1
2
3
4
5
6
7
8
9
10
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'."
        )

但是,断言表达式只在创建bird类之后出现,并且不是可以通过help访问的"真正"docstring。

我知道这是一个开放式的问题,但还有什么更好的方法呢?首先在Bird中定义flap_wings并不是违反规则的,可能只是在pass和docstring中定义。但我就是找不到处理这种情况的"标准"方法。所以我在找任何建议。


对于抽象方法,可以使用abc库:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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方法的子类都会在实例化时引发错误:

1
2
3
4
5
6
7
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

而实现抽象方法的子类将很好地工作:

1
2
3
4
5
6
class BlueJay(Bird):
    def flap_wings(self):
        print("Flappity flap")

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

就记录子类而言,由于所有子类都继承了fly方法,因此可以在其docstring中包含它调用flap_wings方法并希望它存在的内容。